騰訊游戲盒子是由騰訊自主研發的一款專為網頁游戲用戶定制的網頁游戲輔助工具,具有智能加速、防掉線、帳號多開、全屏等特點。
騰訊游戲盒子官網頁面也非常簡單明了,這也是目前很多簡單介紹型網站所采用的風格。頁面下半部分的圓形圖標使用了 CSS3 transform 旋轉屬性,當鼠標移動到上面時會順時針旋轉 20 度,但 IE6 – IE9 不支持該屬性,所以沒有效果。
演示地址:
https://www.361zy.com/demo/379/
下載地址:
https://cloud.06dn.com/s/qR9SW
解壓碼:
LSr69TPA
源:眾成翻譯 譯者:betsey
游戲的靈感
在使用過一段時間的SVG動畫之后,我相當清楚如何利用它來制作動畫片段或者網頁布局。一些動畫庫平臺,例如Greensock,和原生的CSS動畫簡直是絕配。于是我便打算深入地研究一下,看看我能否用這些來制作一款簡單的游戲。就像一個精美的工藝品一樣,好的游戲擁有許多細致的動畫細節。有一天夜里,我的腦海中突然閃現了一個游戲的靈感,我馬上起來,畫了一些草圖,之后給我的哥哥看--他是一個專業的網頁設計師。我們立即開始著手設計,討論了所有的細節動畫后(試著畫出來并且配以音效),我便開始進行游戲開發。
如何玩: 來回彈跳的球是可以改變顏色的。你必須隨時觀察球當前的顏色,并且在球和柱子相接觸的一瞬間,確保兩者的顏色是一樣的。點擊柱子可以改變它的顏色,單擊變紅,雙擊變黃,三擊則變為紫色。
這里是游戲的完整版: http://codepen.io/gregh/full/yVLOyO
創作的過程
在開發這款游戲的過程中,我不斷地遇到問題并重構代碼。其中的一個最主要的問題就是,如何能讓游戲在所有的設備和所有尺寸的顯示器上都看起來不錯。我使用我的Macbook Pro 開發,游戲的畫面很棒。但是當到了 27" iMac screen 上時,整個畫面就看起來特別小,當然在iPhone又會顯得特別大。我真心地希望可以有一把適配所有設備的“萬能鑰匙”。經過了許多次的嘗試之后,我清楚地意識到,傳統的使用媒體查詢的技術來做響應式設計是行不通的。
這篇文章并不是一個教程,因此我將不會逐行的解釋我的代碼。但是,我會展示給你一些十分酷的東西,你可以通過在CodePen上或者是在瀏覽器的調試工具里面修改參數進行測試。同樣,我也會在相應的地方寫出一些參考資料。在CodePen上,我盡可能多的寫出代碼注釋,趕快去看看代碼吧!
十分強大的GSAP讓我理所當然地選擇了它,而我選擇在CodePen上面寫碼的原因是它內置了一個Babel編譯器,這樣我就可以在上面書寫ES6的語法,你不知道Class和箭頭函數有多好用! 關于ES6的特性介紹,你可以點擊這里: https://github.com/DrkSephy/es6-cheatsheet
使用GreenSock制作動畫
我下面假設你熟悉GSAP用法,但如果你不熟悉的話,你可以看下這個“討厭番茄”的人的關于GSAP的教程。https://ihatetomatoes.net/get-greensock-101/
背景動畫
幾乎所有你能在背景上看到的東西都是用SVG制作的。每個波浪是一個獨立的<div>
,每一層的山峰也是一個<div>
,甚至云也是<div>
。當你在制作一個復雜的動畫時,有一點是需要注意的。你完全可以使用一整個SVG當做背景,然后為這個SVG的子元素和路徑來制作動畫。Greensock允許我們這樣做,你需要做的僅僅是為這些SVG的元素(比如說path,group等等)分配一些ID,然后用過ID選擇到他們。但這樣做的問題在于,在移動設備上,這些動畫跑不動。所以你最好是把這些背景元素放在獨立的<div>
里面,然后為這些<div>
添加動畫,我實際上就是使用這些SVG的作為背景。
通過類似于上面的代碼,我們就得到了一些簡單的補間動畫。這些動畫可以將背景水平地移動54個像素(也就是背景的寬度),在這里我們想要背景勻速地移動,所以我們不需要緩動動畫。當我們為每個背景設置不同的移動速度的時候,他們就有表現出了視覺差的效果,看上去很酷吧!
看到畫面上漂浮著一些白色的小圓點了沒?我創造了這些圓點并為他們設置了隨機的位置和尺寸,接著我讓他們做圓周運動。
這樣他們就緩慢地進行圓周運動,但看上去卻像隨機運動一樣。
柱子動畫
每一個柱子里都有一些會動的小元素,這些小元素僅僅是由HTML和CSS制作出來的。使用SASS可以節省很多時間和代碼量(通常情況下是這樣的)。我通過創建形狀的mixins來為這些柱子里面的小東西添加效果。如果我們看下bublble這個效果的代碼,我們就會發現每個圓圈都使用了絕對定位并使用到了這個mixin。在CSS中創造三角形需要很多的代碼,所以mixin就派上了大用場。
讓我們看看紅色的柱子,柱子里面包含著很多的氣泡:
所以現在,如果想要在柱子里面創造一些氣泡的話,我只需要調用這些mixin,設置氣泡的大小,然后讓把他們放在柱子的特定的位置上就好了:
當你需要通過邊框來制作一些小的三角形的時候,你需要用大概20行的css代碼來生成,所以使用mixin實在是太有必要了。
氣泡的動畫
我使用交錯動畫來做這個效果。這個動畫可以操控柱子里面所有的氣泡元素,并且可以讓每個氣泡有一個小小的延時,讓他們不會同時開始運動。點擊這個鏈接,你可以了解更多的關于交錯動畫的知識:http://greensock.com/docs/#/HTML5/GSAP/TweenMax/staggerFrom/
三角形的動畫
在黃色的柱子里面,我使用到了旋轉的效果。但是你可能注意到,有些旋轉是圍繞著X軸的,有些是圍繞著Y軸進行運動的。我們在這里使用到了 cycle屬性。
方塊的動畫
在制作方塊的動畫的時候,我們也使用到了相同的技術。因此,有一半的方塊是從左向右移動的,而另外一般則做反方向的運動。
分數的動畫
讓我們點擊重新開始,再看下這個動畫吧.
我想要分數的動畫有一種“Q彈”的感覺,于是我就寫了幾行代碼來形成這個效果。
為了做出這種“觸電”(或者說是“Q彈”)的效果,我們需要制作正確的緩動動畫。如果你想要看看你可以使用什么樣的緩動方程,看下 Greensock 緩動觀察器:http://greensock.com/ease-visualizer 選擇 Elastic 并調整配置參數,你就可以實時地看運動效果。
彈性盒子
這款游戲的第一個創新性就是使用了“彈性盒子”,如果要是不了解彈性盒子的話,你可以閱讀下這篇優秀的文章: https://css-tricks.com/snippets/css/a-guide-to-flexbox/ 或者看下 Laracasts上的相關系列。一旦你開始使用了彈性盒子,你就再也離不開它。下面我們看下我的的主菜單界面和游戲界面吧。
開始游戲的容器CSS樣式如下:
“flex-direction: column”
表示在容器內部彈性元素的排列方向。 設置為Column,則元素從上到下依次排列。而默認的(row)則將元素從左到右排列。彈性盒子可以這只空白區域,我們可以設定我們是在元素的前面、后面或者周圍放置這些空白區域。動手試下,感受下彈性盒子是多么好玩吧!因為我們設置成了“space-between”
,所以 Top 被放在了頂部, How to Play被放在了底部,而Logo Holder則放在了中間,空白區域被填充在了這些元素之間。 Align-items: center
, 定于交叉軸(這個游戲中代表水平軸)上元素的對齊方式,center表示居中對齊。其中 How to Play也是一個彈性盒子,它的代碼如下:
它也是一個flex元素,我們如果去設定他的flex-direction, 它將使用默認值(row),將其中的三個彈性元素水平的排列。第一個和第三個元素的“flex”參數為1,因此他們將占據所有的空白空間,flex是一個相當高端的特性。同樣的,你也可以通過在How to Play上設置 justify-content: space-around
來達到同樣的目的.我使用flex: 1 的原因是,我想讓中間的一列排在屏幕的最中央。
下面我們看下游戲界面。這個界面也是一個彈性布局。界面有一個柱子容器和一個球的容器。我不想讓球是絕對定位的,因為我通過css讓球剛好坐在柱子上,這樣即使我改變柱子的高度,我也不需要改動其他代碼就可以讓球恰好落到柱子上。因此我將容器的flex-direction設置為 column,正如我所愿,球容器剛好緊挨著柱子的頂部。justify-content: space-between
讓球的容器永遠靠著屏幕的頂部,而柱子容器永遠靠著屏幕的底部。 現在我們給球的容器如下的樣式:
球的容器也是彈性布局,我們將flex方向設為column(這樣Y軸成為了主軸,元素從上到下排列)。之后我們通過 justify-content: flex-end
將球推到了容器的底部,因此,我們便得到了兩個緊密排列的容器,并且第一個容器的內部元素被推到了該容器的最下面,這樣我們便做到了讓球坐在了柱子上的效果。
試想下,如果我們不使用彈性布局會怎么做?我們也許會使用到floats, width: 33.33333% ,position: absolute 和 bottom: 0,我的天啊! Flexbox讓整個界面變得如此整潔有條理,寫碼簡直爽翻了.
讓游戲界面可縮放
做這個游戲,最重要的事情是讓畫面變得可縮放。看下這款游戲在不同尺寸的屏幕上達到了完美的效果!如同我說的,我僅僅是使用了 CSS transform, 這樣做具有它獨特的挑戰性。假如游戲的默認大小是 1200x800px.嗎,如果你的屏幕大小和這個不一樣的話,你需要通過調節系數讓游戲的容器變得大一些或者小一些,也就是做個計算"screenHeight/800\".當然,如果設備的高度大于寬度的時候(當我們的平板或者手機處于垂直模式的時候)我們也需要相應地縮放我們的屏幕,下面是計算縮放比例的代碼 :
顯然僅僅是這樣做不能讓視覺體驗變得完美,所以我們需要在縮小我們的游戲界面的同時讓它垂直水平居中。
因此,我們需要讓整個游戲的容器以相同的尺寸放大,這樣當縮放界面的時候,容器可以100%的占據屏幕的尺寸。如果我們將界面縮小到原始尺寸的一半的時候,我們需要讓它的容器放大到原來的兩倍大小,這樣容器便可以充滿整個屏幕。相反如果屏幕很大的時候,我們需要將界面變為原來的1.2倍,那么容器將相應的從原始尺寸縮小到 screenSize/1.2
后記
我希望你能喜歡這個游戲和我寫的這篇文章,我也希望通過這篇文章,你可以收獲一些新的東西并作出十分精彩的作品
我將持續不斷地完善我的游戲,并相應地更新文章,增加新的玩法或者嘗試些新的技術哦!
本文由眾成翻譯(zcfy.cc)的譯者翻譯完成,搶先閱讀更多優質英文技術文章,歡迎訪問眾成翻譯。
CSS 中有這樣一個模塊:Motion Path 運動模塊,它可以使元素按照自定義的路徑進行移動。本文將為你講解這個模塊屬性的使用,并且利用它實現我小時候電腦課經常玩的一個打字游戲:金山打字的《生死時速》。
css中有這樣一個模塊:Motion Path ,它可以實現元素按不規則路徑移動。
Motion Path模塊包含 offset 的一系列屬性,包括以下幾個:
offset-path 屬性可以取以下幾個值來設置元素的運動路徑:
看下面例子就懂了:
下面代碼中ray射線運動是設置元素朝70度方向運動200px; 按svg路徑運動是讓電車以一個五角星的svg的路線運動; shape圖形是讓電車以polygon()繪制的菱形運動; box是在其父盒子邊緣運動;
設置運動的距離,可以是值,也可以是百分比,例如設置0%處于初始位置,100%就是移動到路徑的終點。所以一般實現元素按不規則路徑移動,就是通過animation修改offset-distance實現的。
設置元素的哪個點沿著路徑運動,例如設置offset-anchor: center bottom為元素的底部中心點沿路徑移動,其他就不多說了,使用方式和background-position一樣。
設置運動的起始位置,只能作用于可以設置position的路線.
例如 ray() 射線運動,可以設置起點位置,或者ellipse()、circle()等這些需要設置position的圖形元素。而且如果在定義路徑時已經寫明了position的話,offset-position是不會生效的,例如circle(50% at 25% 25%)
offset-rotate定義元素沿偏移路徑定位時的方向,默認的話是元素角度會一直和運動路徑的水平角度保持一致,當然你也可以自定義固定角度,或者反向顯示元素(reverse)。
看下面例子就明白了:
游戲開始后,警察在3秒后開始出動,如果警察抓到小偷(位置重合)即游戲失敗。 你需要根據頁面底部的對話正確輸入單詞,即可讓小偷不斷運動,拉開與警察的距離,如果在輸入全部對話前沒有被警察逮到,即闖關成功。
整個游戲其實實現起來很簡單,只需要在設置offset路徑動畫的基礎上加一點點細節就完成了。
找個svg在線編輯網站,設計一個用來當道路等路徑path,然后將兩個位置重合的元素設置相同的運動路徑,即可實現警察和小偷的運動路線。
如何實現警察小偷你追我趕的情景呢?很簡單,警察是一直在運動的,只要小偷不要一直運動,兩者錯開即可。
只需要利用animation-play-state: paused屬性控制小偷運動暫停即可,如果你輸入正確的字符,則設置為animation-play-state: running繼續運動。
如何制作打字控制小偷移動的效果呢?
很簡單,監聽鍵盤輸入即可,如果輸入正確,則將此字符推入答案中,并設置小偷animation-play-state: running讓他繼續運動,延時一小段時間再設置為paused暫停。 答案和題目重合,并且答案設置為了藍色,在答案尾部還利用step逐幀動畫,方便體現打字的進度。因為輸入時,輸入空格也需要光標移動,所以一定要在答案元素上設置white-space: pre以保留空白符的所有空白。另外,為了使要輸入的字符永遠顯示出來,我在推入答案時會使光標調用scrollIntoView()方法使其滾動到可視區。
js復制代碼document.addEventListener('keydown', function (event) {
const myinput = answer.textContent
if (event.key === words[myinput.length]) {
timer && clearTimeout(timer)
answer.textContent = myinput + event.key
thief.style.setProperty('--paused', 'running');
document.querySelector('.show').scrollIntoView(true)
timer = setTimeout(() => {
thief.style.setProperty('--paused', 'paused');
}, 400);
}
});
setTimeout(() => {
checkCollision()
police.style['animation-play-state'] = 'running'
}, 2000);
如果做碰撞檢測呢并顯示結果呢?
碰撞檢測其實很簡單,只需要利用getBoundingClientRect()方法獲取警察和小偷的定位,判斷是否幾乎重合即可。判斷輸贏的方式為:如果你在打完所有文字之前不被逮捕則闖關成功,否則闖關失敗。
js復制代碼// 碰撞檢測
function checkCollision() {
const policeRect = police.getBoundingClientRect()
const thiefRect = thief.getBoundingClientRect()
if (answer.textContent.length >= words.length) {
showResult(true)
return
}
if (Math.abs(policeRect.x - thiefRect.x) < 2 && Math.abs(policeRect.y - thiefRect.y) < 2) {
showResult()
return
}
requestAnimationFrame(checkCollision)
}
// 結局判斷
function showResult(flag) {
if (flag) {
document.querySelector('.success').style.display = 'grid'
} else {
document.querySelector('.fail h1').textContent =
`你被逮捕了!${document.querySelector(".timing").textContent}`
document.querySelector('.fail').style.display = 'grid'
}
}
學如逆水行舟,不進則退~
作者:前端阿彬 鏈接:https://juejin.cn/post/7349752708386553910 來源:稀土掘金 著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。