【暑假記憶】消暑神器,我用CSS復刻了一個遊戲機

語言: CN / TW / HK

theme: qklhk-chocolate highlight: atelier-dune-light


“我正在參加「初夏創意投稿大賽」詳情請看:初夏創意投稿大賽

夏日回憶

我小時候,家裡的庭院有一棵枝繁葉茂的樹,那時候家裡沒有空調,夏天會在樹蔭下鋪個席子,或是午睡,或是看書。後來,家裡給我買了一臺掌上游戲機,那個時候還挺奢侈的。於是,暑假大部分時間都是在俄羅斯方塊的旋轉、移動中度過的。

我用CSS復刻了一個遊戲機

記憶中的遊戲機已經模糊了,於是我搜索了一下游戲機的圖片。尤其卡通圖片,圓乎乎的真可愛。遊戲機的主體和螢幕是矩形的,按鍵是圓形或者圓角矩形。有趣又比較好實現。

所以我便用CSS復刻了一個遊戲機。

碼上掘金

“碼上掘金”可以線上進行程式碼效果的即時預覽、演示,非常方便。下面是遊戲機的預覽。 https://code.juejin.cn/pen/7101709588033961991

UI展示

機體

  • 遊戲機的主體是一個矩形,帶有邊框和弧度;
  • 為了呈現立體感,通過box-shadow遊戲機主體設定了向外的陰影;

css

js .player { width: 280px; height: 460px; background: #ffc600; border: 6px solid #5a1f12; border-radius: 15px 15px 45px 15px; position: relative; box-shadow: 30px 20px 10px 10px #9e988b; }

html

```js

```

聽筒

掌上游戲機在玩遊戲的時候,會有音效,所以我設計了一個聽筒。

  • 聽筒是一個平面圓角矩形,通過設定border-radius的值可以實現兩邊的圓角;

css

js .head { width: 100%; height: 26px; position: absolute; top: 0; left: 0; border-bottom: 5px solid #5a1f12; } .head::before { content: ''; width: 6px; height: 26px; background: #5a1f12; position: absolute; top: 0; left: 20px; } .head::after { content: ''; width: 6px; height: 26px; background: #5a1f12; position: absolute; top: 0; right: 20px; } .receiver { width: 50px; height: 8px; background: #eba260; border: 4px solid #5a1f12; border-radius: 8px; position: absolute; top: 5px; left: 35px; }

html

```js

```

螢幕

螢幕除了邊框之外,顯示部分由兩個內容構成,開機前和開機後,兩個不共存。

開機前

  • 開機前展示綠色的螢幕和反光效果,我小時的遊戲機螢幕是淺綠色的,這個我還有點印象;
  • 反光效果,主要是為了增加趣味性和表現螢幕的光亮感。我將反光效果設計為一個白條從螢幕上方移動到下方,這個效果通過animation實現;

css

js .screen { width: 220px; height: 170px; background: #9c6766; border: 5px solid #5a1f12; border-radius: 10px 10px 30px 10px; position: absolute; top: 40px; left: 50%; margin-left: -115px; } .monitor { width: 180px; height: 120px; background: #d5eabd; border: 5px solid #5a1f12; margin: 20px auto; position: relative; overflow: hidden; } .monitor .light { width: 20px; height: 220px; background: #e2f0d8; position: absolute; top: -33px; left: -23px; transform: rotate(44deg); animation: monitorlight 3s infinite; } @keyframes monitorlight { 50% { left: 80%; } 51% { left: 80%; opacity: 1; } 61% { left: 80%; opacity: 0.3; } 71% { left: 80%; opacity: 1; } 81% { left: 80%; opacity: 0.3; } 91% { left: 80%; opacity: 1; } 100% { left: 80%; opacity: 1; } }

html

```js

```

開機後

  • 開機後展示俄羅斯方塊的介面,包括左側的遊戲區域和右側的遊戲記錄兩個部分;
  • 遊戲區域目前僅實現展示遊戲名稱的功能;

css

js .screen .game { width: 190px; height: 150px; background: #d5eabd; border-radius: 10px 10px 30px 10px; margin: 10px auto; display: none; } .game .left { float: left; width: 52%; height: 128px; border: 1px solid #333; margin: 10px 0 0 10px; position: relative; } .game .game-name { width: 100%; height: 100%; position: absolute; top: 0; left: 0; color: #000; line-height: 1; background: rgba(158, 174, 134, 0.8); justify-content: center; display: none; } .game .game-name .name-box { animation: 1.5s linear gamename forwards; font-size: 15px; padding: 54px 0 0 10px; } @keyframes gamename { 30% { opacity: 0.3; } 60% { opacity: 1; } 90% { opacity: 0.3; } 91% { opacity: 1; } 100% { opacity: 1; } } .game .left-content { position: absolute; top: 10px; left: 8px; } .game .left-box .integral-block.b { border: 2px solid #333; } .game .left-box .integral-block.b::after { background: #333; } .game .right { float: right; width: 30%; font-size: 12px; font-weight: 300; text-align: left; line-height: 1.5; padding: 10px; color: #000; } .game .integral-num { font-size: 13px; font-weight: 500; text-align: right; } .game .integral-graph { position: relative; } .game .integral-box { position: relative; height: 14px; width: 40px; } .game .integral-box .integral-block { border: 2px solid #333; } .game .integral-box .integral-block::after { background: #333; } .game .integral-block { display: block; width: 6px; height: 6px; padding: 1px; border: 2px solid #9eae86; margin: 0 2px 2px 0; float: left; } .game .integral-block::after { content: ''; display: block; width: 6px; height: 6px; background: #9eae86; overflow: hidden; } .game .integral-box1 { top: 4px; left: 13px; } .game .integral-box2 { top: 7px; left: 27px; }

html

```js

遊戲開始
最高分
10
起始行
0
下一個

; ```

分割線

  • 分割線為了更好區分螢幕和按鍵兩個區域;
  • 包括左右兩個橫向和中間六個點;

css

js .dividing { width: 100%; height: 24px; display: flex; justify-content: space-between; align-items: center; position: absolute; top: 220px; left: 0; } .dleft { width: 50px; height: 5px; background: #5a1f12; margin-left: 30px; border-radius: 5px; } .dcenter { display: flex; } .dspot { width: 3px; height: 5px; background: #5a1f12; margin-right: 3px; border-radius: 3px; } .dright { width: 80px; height: 5px; background: #5a1f12; margin-right: 30px; border-radius: 5px; }

html

```js

; ```

按鍵

  • 上下左右操作按鍵,由圓和十字圖形組成,十字圖形通過橫向和豎向的矩形組成,為了增加立體感,十字的矩形添加了外部的陰影;
  • 開始按鍵,右側傾斜的圓角矩形上側的紅色圓點為開始按鍵,點選之後,螢幕點亮並展示內容,同時開始按鍵不可重複點選,停止按鍵可以點選;
  • 停止按鍵右側傾斜的圓角矩形下側的紅色圓點為開始按鍵,點選之後,螢幕關閉展示綠色螢幕,同時停止按鍵不可重複點選,開始按鍵可以點選;
  • 聲音按鍵,底部兩個圓角矩形為聲音按鍵;

css

js .push-direction { width: 80px; height: 80px; background: #ee9731; border: 4px solid #5a1f12; border-radius: 50%; position: absolute; top: 260px; left: 15px; } .push-direction::before { content: ''; width: 54px; height: 20px; background: #7b4a45; position: absolute; top: 30px; left: 13px; box-shadow: 0 -3px 0 0 #fff; border-radius: 5px; } .push-direction::after { content: ''; width: 20px; height: 54px; background: #7b4a45; position: absolute; top: 13px; right: 30px; box-shadow: 0 -3px 0 0 #fff; border-radius: 5px; } .push-control { width: 36px; height: 80px; background: #eb9430; border: 4px solid #5a1f12; border-radius: 40px; position: absolute; top: 260px; right: 35px; transform: rotate(55deg); } .push-control .begin, .push-control .stop { width: 26px; height: 26px; line-height: 26px; text-align: center; color: #fff; background: #ff4822; position: absolute; left: 6px; box-shadow: inset 0 3px 0 0 #fff; border-radius: 50%; font-size: 13px; cursor: pointer; } .push-control .begin { top: 10px; } .push-control .stop { top: 45px; } .push-sound { width: 16px; height: 50px; background: #864949; position: absolute; top: 350px; border: 2px solid #5a1f12; border-radius: 16px; box-shadow: inset 3px 0 0 0 #fff; transform: rotate(60deg); } .push-sound::before { content: ''; width: 24px; height: 4px; background: #5a1f12; position: absolute; bottom: 21px; left: 12px; border-radius: 4px; transform: rotate(-90deg); } .push-sound-top { left: 80px; } .push-sound-bottom { left: 140px; }

html

```js

B
S

```

js

```js var leftBox = document.getElementsByClassName('left-box'); var pushBegin = document.getElementById('pushBegin'); var pushStop = document.getElementById('pushStop'); var monitor = document.getElementById('monitor'); var game = document.getElementById('game'); var gameName = document.getElementById('gameName');

// 螢幕展示方法 function show() { monitor.style.display = 'none'; game.style.display = 'block'; // 設定開始按鈕不可以點選 pushBegin.disabled = false; // 設定關閉按鈕可以點選 pushStop.disabled = true; setTimeout(function () { for (var i = 0; i < leftBox.length; i++) { var block = leftBox[i].getElementsByClassName('integral-block'); for (var j = 0; j < block.length; j++) { block[j].classList.add('b'); } } }, 800); setTimeout(function () { gameName.style.display = 'block'; }, 1500); }

// 螢幕停止方法 function stop() { monitor.style.display = 'block'; game.style.display = 'none'; // 設定開始按鈕可以點選 pushBegin.disabled = true; // 設定關閉按鈕不可以點選 pushStop.disabled = false; for (var i = 0; i < leftBox.length; i++) { var block = leftBox[i].getElementsByClassName('integral-block'); for (var j = 0; j < block.length; j++) { block[j].classList.remove('b'); } } } pushBegin.onclick = show; pushStop.onclick = stop; ```

總結

這次用CSS實現兒時的遊戲機,帶給我很多啟發,一大批卡通形象匯聚到了我的大腦中,等我有時間慢慢實現。

創作的過程真的很有意思,程式碼成了我的畫筆,作為一個不擅長繪畫但是喜歡卡通的人,程式碼幫助我實現了想實現的畫作。(^▽^)

不過,還有兩個功能待實現。第一個是按行點亮方塊的功能,另一個是俄羅斯方塊遊戲的開發。前面這個最近在探索中。後面的功能,演算法是我的短板,也希望未來能補足。