Pull to refresh

Game Boy на CSS + Эмулятор

Доброго времени суток, уважаемые хаброжители.

На днях у меня появилась идея написать Game Boy, на чистом CSS.

После того как Game Boy был реализован, прибывая на codepen, поступали разные интересные предложения, о том, как бы оживить его.

По мере того как Game Boy приобретал своих сторонников, я решил опубликовать статью: «Как я написал Game Boy » и подключил эмулятор.

Рабочая версия Дубасим: в старый добрый «Mario».

Среда для разработки Sublime text и webkit браузер.

Работа оказалась абсолютно не сложная, скорее увлекательная.

image

Полагаю, вы хорошо знакомы с CSS, Javascript, HTML5, и вам не составит труда разобраться в моей писанине.
В HTML разметке присутствуют комментарии к дивам.

1. HTML, Javascript

<body>
	<div class="wrapper"> Тело геймбоя, я поместил под элементом враппер, мозила  и експлорер, почему-то игнорируют градиентный бекгаунд у элемента body  (если в родителе есть потомок с абсолютным позиционированием.) Решение проблемы я не нашел,  по сему пришлось сделать вот такую мутку .
		<p>by ANTON ESSENTIAL</p>
	</div>
	<div class="gameboy"> Тело геймбоя
		<hr class="l-1">
		<hr class="l-2">
		<hr class="l-3">
		<hr class="l-4">
		<hr class="l-5">
		<hr class="l-6">
		<hr class="l-7">
		<hr class="l-8">
		<p>dot matrix with stereo sound</p> 
		<div class="reflex"> 
			<div class="display-2"></div>   Дисплей 
			<canvas id="LCD" width='147' height='134'></canvas> Дисплей 
			<div class="display"></div>  Див с эффектом (эффект пластика на дисплеей) 
			<span class="diod"></span>  Диод 
		</div>
		<ul class="buttons"> <b>Кнопки (А.B)</b>
			<li></li>
			<li></li>
		</ul>
		<ul class="buttons-2"><b> Кнопки (Start, Select)</b>
			<li class='start' onclick='gb_Run();'></li>
			<li class='pause' disabled onclick='gb_Pause();'></li>
		</ul>
		<ul class="speacker">  Динамик 
			<li></li>
			<li></li>
			<li></li>
			<li></li>
			<li></li>
			<li></li>
		</ul>
		<div class="stick">  Стик 
			<ul class="left">
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
			<ul class="right">
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
			<ul class="top">
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
			<ul class="bottom">
				<li></li>
				<li></li>
				<li></li>
				<li></li>
				<li></li>
			</ul>
			<ul class="circle">
				<li></li>
			</ul>
		</div>
	</div>

	<select id="CARTRIDGE" row='1' onchange='gb_Insert_Cartridge(this.value,true);'>   Селектор образов (картриджы) 
          <option value="Super-Mario-Land.gb">Super-Mario-Land</option>
          <option value="mc-mrder.gb">PD mc-mrder</option>
          <option value="20y.gb">PD 20y</option>
          <option value="wario_walking.gb">PD wario_walking</option>
	</select><br>
	<input id='BR' type="button" value='Run' onfocus='this.blur();' onclick='gb_Run();'>    Управление 
	<input id='BP' type="button" value='Pause' onfocus='this.blur();' disabled onclick='gb_Pause();'>
	<input id='BS' type="button" value='Step' onfocus='this.blur();' onclick='gb_Step();'>
	<input id="BS" type="button" value="Reset"  onfocus="this.blur();" onclick="gb_Insert_Cartridge($('CARTRIDGE').value,true);"/>
	<input id='BX' type="button" value='Size x2' onfocus='this.blur();' onclick='gb_Resize_LCD();'>
	<div id="DEBUGGER"></div>

	<script type='text/javascript' src='js/cssrefresh.js'></script>
	<script type='text/javascript' src='js/jquery-1.10.2.min.js'></script>
	<script type='application/x-javascript' src='js/toolbox.js'></script>
	<script type='application/x-javascript' src='js/scrollbar.js'></script>
	<script type='application/x-javascript' src='js/jsgb.cpu.js'></script>
	<script type='application/x-javascript' src='js/jsgb.memory.js'></script>
	<script type='application/x-javascript' src='js/jsgb.rom.js'></script>
	<script type='application/x-javascript' src='js/jsgb.interrupts.js'></script>
	<script type='application/x-javascript' src='js/jsgb.input.js'></script>
	<script type='application/x-javascript' src='js/jsgb.lcd.js'></script>
	<script type='application/x-javascript' src='js/jsgb.timers.js'></script>
	<script type='application/x-javascript' src='js/jsgb.debugger.js'></script>
	<script type='application/x-javascript' src='js/jsgb.gameboy.js'></script>

	<script type='application/x-javascript'>   Ресайз дисплея 

		var gbSeconds = 0;
		var gbFrames = 0;

		function gb_Resize_LCD() {
			if($('BX').value=='Size x2') {
				$('BX').value='Size x3';
				$('LCD').style.width='320px';
				$('LCD').style.heght='288px';
			}
			else if($('BX').value=='Size x3') {
				$('BX').value='Size x1';
				$('LCD').style.width='480px';
				$('LCD').style.heght='432px';
			}
			else {
				$('BX').value='Size x2';
				$('LCD').style.width='147px';
				$('LCD').style.heght='134px';
			}
		}

		function gb_Show_Fps() {
			gbFrames+=gbFPS;
			gbSeconds++;
			$('STATUS').innerHTML =
				'Running: '+gbFPS+' '+
				'fps - Averenge: '+(gbFrames/gbSeconds).toFixed(2)+' - '+
				'Bank switches/s: '+gbBankSwitchCount;
			gbFPS=0;
			gbBankSwitchCount=0;
		}

		function gb_Toggle_Debugger(show) {
			$('DEBUGGER').style.heght=(show)?'auto':'0px';
		}

		window.onload = function(){
			gb_Insert_Cartridge($('CARTRIDGE').value, false);
			gb_Toggle_Debugger($('TOGGLE_DEBUGGER').checked);
		}

	</script>

	<script>   По событию клик, появляется канвас [дисплей] 
		jQuery(function($) {
			$('.start').click(function(){
				$('#LCD').fadeIn(1);
			});
		});
	</script>
</body>
</html>


В представленном ниже коде, я не буду упоминать про резет, либо нармолайз цсс.
Так же я опустил префиксы, чтобы сэкономить время.

2. CSS
body {
	background: rgb(32, 32, 32);
}

.wrapper {
	position: relative;
	top: 50px;
	width: 100%;
	height: 645px;
	background-image: linear-gradient(-32deg,#e41717, #72075c 78%);
	-webkit-filter: blur(2px);
}

.gameboy {
	position: absolute;
	top: 150px;
	left: 200px;
	width: 265px;
	height: 433px;
	border: 2px solid rgb(153, 153, 153);
	border-radius: 10px 10px 77px 10px;
	background-image: -webkit-linear-gradient(#adb6b3, #bec2c1 50%);
	box-shadow: -5px 6px 20px rgba(0, 0, 0, 0.46),
	-21px 17px 65px rgba(0, 0, 0, 0.46),
	inset 3px 0 10px #616465,
	inset -3px 0 4px #8e918e,
	inset -7px 0 7px #dfdfdf,
	inset 1px 0px 3px #66696a,
	inset 0 3px 7px #919496,
	inset 0 4px 10px white;
}

.wrapper p {
	position: relative;
	top: 511px;
	left: 534px;
	display: inline-block;
	color: white;
	font-weight: bold;
	font-size: 26px;
	font-family: "Arial"
}

.gameboy p {
	position: absolute;
	top: 45px;
	left: 85px;
	z-index: 2;
	color: rgba(255, 255, 255, 0.63);
	text-transform: uppercase;
	font-size: 7px;
	font-family: "Arial"
}

.reflex {
	position: relative;
	top: 36px;
	left: 15px;
	overflow: hidden;
	width: 232px;
	height: 177px;
	border-top: 1px solid #3d4844;
	border-right: 1px solid #3d4844;
	border-bottom: 1px solid #1d2120;
	border-left: 2px solid rgba(29, 33, 32, 0.57);
	border-radius: 10px 10px 53px 10px;
	background: #485055;
	box-shadow: inset 0 1px 1px #aab3b0,
	0 1px 0 #5b5e63,
	0 2px 0 #ebebeb,
	1px 0 2px #d3d3d3,
	-1px 0 2px #cfcfcf,
	inset -1px 0 2px rgba(255, 255, 255, 0.44);
}

.display {
	position: absolute;
	z-index: 3;
	width: 232px;
	height: 177px;
	border-radius: 10px 10px 53px 10px;
	background-image: -webkit-linear-gradient(46deg, rgba(72, 80,85, 0), rgba(143, 151, 156, 0.58)80%);
}

.display-2 {
	position: absolute;
	top: 21px;
	left: 43px;
	z-index: 2;
	width: 147px;
	height: 134px;
	border-top: 1px solid #394b21;
	border-right: 1px solid #36472f;
	background: #5f953d;
	box-shadow: inset -2px 5px 10px #2a421a;
	opacity: .5;
}

#LCD {
	display: none;
	position: absolute;
	top: 21px;
	left: 43px;
}

.l-1 {
	position: absolute;
	top: 11px;
	width: 265px;
	height: 3px;
	border: none;
	border-radius: 50px;
	background-image: -webkit-linear-gradient(#87928d, #a9b2af 90%);
	opacity: .6;
}

.l-2 {
	position: absolute;
	top: -8px;
	left: 20px;
	width: 3px;
	height: 19px;
	border: none;
	border-radius: 5px 5px 0 0;
	background-image: -webkit-linear-gradient(#a9b2af, #87908d 90%);
	opacity: .6;
}

.l-3 {
	position: absolute;
	top: -8px;
	right: 20px;
	width: 3px;
	height: 19px;
	border: none;
	border-radius: 5px 5px 0 0;
	background-image: -webkit-linear-gradient(#a9b2af, #87908d 90%);
	opacity: .6;
}

.l-4 {
	position: absolute;
	top: 36px;
	left: 26px;
	z-index: 2;
	width: 51px;
	height: 3px;
	border: none;
	background: #543363;
}

.l-5 {
	position: absolute;
	top: 42px;
	left: 26px;
	z-index: 2;
	width: 51px;
	height: 3px;
	border: none;
	background: #30345a;
}

.l-6 {
	position: absolute;
	top: 36px;
	left: 217px;
	z-index: 2;
	width: 20px;
	height: 3px;
	border: none;
	background: #543363;
}

.l-7 {
	position: absolute;
	top: 42px;
	left: 217px;
	z-index: 2;
	width: 20px;
	height: 3px;
	border: none;
	background: #30345a;
}

.l-8 {
	position: absolute;
	display: none;
}

.diod {
	position: absolute;
	top: 61px;
	left: 12px;
	display: block;
	width: 9px;
	height: 9px;
	border: 1px solid #ac774d;
	border-radius: 50px;
	background: #e4b443;
	box-shadow: 0 0 5px #ac774d,
	-1px 1px 1px rgba(83, 53, 41, 0.99),
	inset 0 1px 2px #fcb251;
	-webkit-animation:light linear 3s infinite;
}

.buttons {
	position: absolute;
	top: 242px;
	left: 179px;
	padding: 6px;
	border-radius: 50px;
	box-shadow: 1px 1px 5px rgba(255, 255, 255, 0.21),
	-1px 1px 0px #babdbc,
	inset 0 12px 22px rgba(0, 0, 0, 0.12);
	-webkit-transform: rotate(64deg);
}

.buttons li {
	width: 30px;
	height: 30px;
	border: 1px solid rgba(68, 32, 54, 1);
	border-radius: 100%;
	background-image: linear-gradient(6deg,rgba(133, 50, 108, 0.61),#6d1851 89%);
	box-shadow: inset 1px 2px 4px #a87493,
	-1px -1px 2px #000,
	3px 6px 7px rgba(125, 136, 134, 0.79);
}

.buttons li:first-child {
	margin-bottom: 17px;
}

.buttons-2 {
	position: absolute;
	top: 348px;
	left: 103px;
	-webkit-transform: rotate(64deg);
}

.buttons-2 li {
	position: absolute;
	width: 9px;
	height: 34px;
	border-radius: 50px;
	background-image: linear-gradient(269deg, #6f7875, #9b9b9b 71%);
	box-shadow: 1px 1px 1px rgba(226, 226, 226, 0.97),
	-1px -1px 2px #767a79,
	inset 1px 1px 1px #a3aca9;
}

.buttons-2 li:last-child {
	position: absolute;
	bottom: 7px;
	left: 20px;
}

.speacker {
	position: absolute;
	top: 344px;
	left: 174px;
	-webkit-transform: rotate(64deg);
}

.speacker li {
	margin-bottom: 8px;
	width: 42px;
	height: 6px;
	border-radius: 10px;
	box-shadow: 1px 1px 1px rgba(255, 255, 255, 0.7),
	inset 2px 1px 3px #5b5a53,
	inset 1px -1px black;
}

.stick {
	position: absolute;
	top: 252px;
	left: 14px;
	width: 93px;
	height: 93px;
	border-radius: 50%;
	box-shadow: inset -7px 10px 22px #c7cbca,
	inset 7px -10px 22px #b8b8b8;
}

.top {
	position: absolute;
	top: 15px;
	left: 34px;
	width: 24px;
	height: 21px;
	border-radius: 2px 2px 0 0;
	background-image: linear-gradient(90deg,#282c2b, #9b9b9b 119%);
	box-shadow: 1px -1px 1px rgb(53, 53, 53),
	-4px 3px 7px rgba(96, 96, 98, 0.64);
}

.top li {
	margin: 2px;
	width: 20px;
	height: 2px;
	border-radius: 2px;
	background: #353837;
	box-shadow: inset 0 -1px 1px #494c4b;
}

.left {
	position: absolute;
	top: 36px;
	left: 56px;
	width: 24px;
	height: 22px;
	border-radius: 2px 2px 0 0;
	background-image: linear-gradient(303deg,#282c2b, #9b9b9b 111%);
	box-shadow: 1px -1px 1px rgb(53, 53, 53);
	-webkit-transform: rotate(90deg);
}

.left li {
	margin: 2px;
	width: 20px;
	height: 2px;
	border-radius: 2px;
	background: #353837;
	box-shadow: inset 0 -1px 1px #494c4b;
}

.bottom {
	position: absolute;
	top: 58px;
	left: 34px;
	width: 24px;
	height: 21px;
	border-radius: 0 0 2px 2px;
	background-image: linear-gradient(55deg,#131716, #6a706f 147%);
	box-shadow: -5px 0px 6px #606362;
}

.bottom li {
	margin: 2px;
	width: 20px;
	height: 2px;
	border-radius: 2px;
	background: #050908;
	box-shadow: inset 0 -1px 1px #343839;
}

.right {
	position: absolute;
	top: 36px;
	left: 12px;
	width: 24px;
	height: 22px;
	border-radius: 0 0 2px 2px;
	background-image: linear-gradient(290deg,#131716, #6a706f 173%);
	box-shadow: 2px 3px 7px rgb(53, 53, 53);
	-webkit-transform: rotate(90deg);
}

.right li {
	margin: 2px;
	width: 20px;
	height: 2px;
	border-radius: 2px;
	background: #050908;
	box-shadow: inset 0 -1px 1px #433839;
}

.circle {
	position: absolute;
	top: 36px;
	left: 35px;
	z-index: 5;
	width: 22px;
	height: 22px;
	background-image: linear-gradient(-134deg, #656666, #2e3231 60%);
}

.circle li {
	position: absolute;
	top: 2px;
	left: 2px;
	width: 16px;
	height: 16px;
	border: 1px solid rgba(39, 42, 41, 0.91);
	border-radius: 16px;
	background: #4b4e4d;
	box-shadow: inset 2px -1px 8px #868787,
	inset 3px -1px 10px black;
}

@-webkit-keyframes light {
	0% {
		box-shadow: 0 0 0 #ffa300;
	}
	50% {
		box-shadow: 0 0 24px #ffa300;
	}
	100% {
		box-shadow: 0 0 0 #ffa300;
	}
}

#DEBUGGER {
	visibility: hidden;
}

.start:hover,
.pause:hover {
	cursor: pointer;
}

input, select {
	position: relative;
	top: 100px;
}


Надеюсь, вам было интересно.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.