Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
浪里小白虫…
HTML-CSS-JS_01
提交
eb1a2959
H
HTML-CSS-JS_01
项目概览
浪里小白虫…
/
HTML-CSS-JS_01
与 Fork 源项目一致
Fork自
特立独行的猫a / HTML-CSS-JS
通知
1
Star
0
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
0
列表
看板
标记
里程碑
合并请求
0
DevOps
流水线
流水线任务
计划
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
H
HTML-CSS-JS_01
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
0
Issue
0
列表
看板
标记
里程碑
合并请求
0
合并请求
0
Pages
DevOps
DevOps
流水线
流水线任务
计划
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
流水线任务
提交
Issue看板
体验新版 GitCode,发现更多精彩内容 >>
提交
eb1a2959
编写于
3月 28, 2023
作者:
6
6420f2de3cded528672f792b
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Auto commit
上级
9949aabe
变更
4
隐藏空白更改
内联
并排
Showing
4 changed file
with
644 addition
and
14 deletion
+644
-14
index.html
index.html
+17
-14
ninja.css
ninja.css
+127
-0
ninja.js
ninja.js
+499
-0
ninja1.js
ninja1.js
+1
-0
未找到文件。
index.html
浏览文件 @
eb1a2959
<!DOCTYPE html>
<html
lang=
"en"
>
<head>
<meta
charset=
"UTF-8"
>
<meta
http-equiv=
"X-UA-Compatible"
content=
"IE=edge"
>
<meta
name=
"viewport"
content=
"width=device-width, initial-scale=1.0"
>
<link
href=
"style.css"
rel=
"stylesheet"
type=
"text/css"
/>
<title>
InsCode
</title>
</head>
<body>
<html>
<head>
<meta
charset=
"utf-8"
>
<meta
name=
"viewport"
content=
"width=device-width"
>
<title>
repl.it
</title>
<link
href=
"ninja.css"
rel=
"stylesheet"
type=
"text/css"
/>
</head>
<body>
<div
class=
"container"
>
<img
src=
"src/assets/logo.svg"
alt=
"InsCode"
>
<div>
欢迎来到 InsCode
</div>
</div>
<script
src=
"script.js"
></script>
</body>
<div
id=
"score"
></div>
<canvas
id=
"game"
width=
"375"
height=
"375"
></canvas>
<div
id=
"introduction"
>
Hold down the mouse to stretch out a stick
</div>
<div
id=
"perfect"
>
DOUBLE SCORE
</div>
<button
id=
"restart"
>
RESTART
</button>
</div>
<script
src=
"ninja.js"
></script>
</body>
</html>
\ No newline at end of file
ninja.css
0 → 100644
浏览文件 @
eb1a2959
html
,
body
{
height
:
100%
;
margin
:
0
;
}
body
{
font-family
:
"Segoe UI"
,
Tahoma
,
Geneva
,
Verdana
,
sans-serif
;
cursor
:
pointer
;
}
.container
{
display
:
flex
;
justify-content
:
center
;
align-items
:
center
;
height
:
100%
;
}
#score
{
position
:
absolute
;
top
:
30px
;
right
:
30px
;
font-size
:
2em
;
font-weight
:
900
;
}
#introduction
{
width
:
200px
;
height
:
150px
;
position
:
absolute
;
font-weight
:
600
;
font-size
:
0.8em
;
font-family
:
"Segoe UI"
,
Tahoma
,
Geneva
,
Verdana
,
sans-serif
;
text-align
:
center
;
transition
:
opacity
2s
;
}
#restart
{
width
:
120px
;
height
:
120px
;
position
:
absolute
;
border-radius
:
50%
;
color
:
white
;
background-color
:
red
;
border
:
none
;
font-weight
:
700
;
font-size
:
1.2em
;
font-family
:
"Segoe UI"
,
Tahoma
,
Geneva
,
Verdana
,
sans-serif
;
display
:
none
;
cursor
:
pointer
;
}
#perfect
{
position
:
absolute
;
opacity
:
0
;
transition
:
opacity
2s
;
}
#youtube
,
#youtube-card
{
display
:
none
;
}
@media
(
min-height
:
425px
)
{
/** Youtube logo by https://codepen.io/alvaromontoro */
#youtube
{
z-index
:
2
;
display
:
block
;
width
:
100px
;
height
:
70px
;
position
:
absolute
;
bottom
:
20px
;
left
:
20px
;
background
:
red
;
border-radius
:
50%
/
11%
;
transform
:
scale
(
0.8
);
transition
:
transform
0.5s
;
}
#youtube
:hover
,
#youtube
:focus
{
transform
:
scale
(
0.9
);
}
#youtube
::before
{
content
:
""
;
display
:
block
;
position
:
absolute
;
top
:
7.5%
;
left
:
-6%
;
width
:
112%
;
height
:
85%
;
background
:
red
;
border-radius
:
9%
/
50%
;
}
#youtube
::after
{
content
:
""
;
display
:
block
;
position
:
absolute
;
top
:
20px
;
left
:
40px
;
width
:
45px
;
height
:
30px
;
border
:
15px
solid
transparent
;
box-sizing
:
border-box
;
border-left
:
30px
solid
white
;
}
#youtube
span
{
font-size
:
0
;
position
:
absolute
;
width
:
0
;
height
:
0
;
overflow
:
hidden
;
}
#youtube
:hover
+
#youtube-card
{
display
:
block
;
position
:
absolute
;
bottom
:
12px
;
left
:
10px
;
padding
:
25px
25px
25px
130px
;
width
:
300px
;
background-color
:
white
;
}
}
ninja.js
0 → 100644
浏览文件 @
eb1a2959
// Extend the base functionality of JavaScript
Array
.
prototype
.
last
=
function
()
{
return
this
[
this
.
length
-
1
];
};
Math
.
sinus
=
function
(
degree
)
{
return
Math
.
sin
((
degree
/
180
)
*
Math
.
PI
);
};
// Game data
let
phase
=
"
waiting
"
;
let
lastTimestamp
;
let
heroX
;
let
heroY
;
let
sceneOffset
;
let
platforms
=
[];
let
sticks
=
[];
let
trees
=
[];
// Todo: Save high score to localStorage (?)
let
score
=
0
;
const
canvasWidth
=
375
;
const
canvasHeight
=
375
;
const
platformHeight
=
100
;
const
heroDistanceFromEdge
=
10
;
const
paddingX
=
100
;
const
perfectAreaSize
=
10
;
const
backgroundSpeedMultiplier
=
0.2
;
const
hill1BaseHeight
=
100
;
const
hill1Amplitude
=
10
;
const
hill1Stretch
=
1
;
const
hill2BaseHeight
=
70
;
const
hill2Amplitude
=
20
;
const
hill2Stretch
=
0.5
;
const
stretchingSpeed
=
4
;
const
turningSpeed
=
4
;
const
walkingSpeed
=
4
;
const
transitioningSpeed
=
2
;
const
fallingSpeed
=
2
;
const
heroWidth
=
17
;
// 24
const
heroHeight
=
30
;
// 40
const
canvas
=
document
.
getElementById
(
"
game
"
);
canvas
.
width
=
window
.
innerWidth
;
// Make the Canvas full screen
canvas
.
height
=
window
.
innerHeight
;
const
ctx
=
canvas
.
getContext
(
"
2d
"
);
const
introductionElement
=
document
.
getElementById
(
"
introduction
"
);
const
perfectElement
=
document
.
getElementById
(
"
perfect
"
);
const
restartButton
=
document
.
getElementById
(
"
restart
"
);
const
scoreElement
=
document
.
getElementById
(
"
score
"
);
// Initialize layout
resetGame
();
function
resetGame
()
{
// Reset game progress
phase
=
"
waiting
"
;
lastTimestamp
=
undefined
;
sceneOffset
=
0
;
score
=
0
;
introductionElement
.
style
.
opacity
=
1
;
perfectElement
.
style
.
opacity
=
0
;
restartButton
.
style
.
display
=
"
none
"
;
scoreElement
.
innerText
=
score
;
platforms
=
[{
x
:
50
,
w
:
50
}];
generatePlatform
();
generatePlatform
();
generatePlatform
();
generatePlatform
();
sticks
=
[{
x
:
platforms
[
0
].
x
+
platforms
[
0
].
w
,
length
:
0
,
rotation
:
0
}];
trees
=
[];
generateTree
();
generateTree
();
generateTree
();
generateTree
();
generateTree
();
generateTree
();
generateTree
();
generateTree
();
generateTree
();
generateTree
();
heroX
=
platforms
[
0
].
x
+
platforms
[
0
].
w
-
heroDistanceFromEdge
;
heroY
=
0
;
draw
();
}
function
generateTree
()
{
const
minimumGap
=
30
;
const
maximumGap
=
150
;
const
lastTree
=
trees
[
trees
.
length
-
1
];
let
furthestX
=
lastTree
?
lastTree
.
x
:
0
;
const
x
=
furthestX
+
minimumGap
+
Math
.
floor
(
Math
.
random
()
*
(
maximumGap
-
minimumGap
));
const
treeColors
=
[
"
#6D8821
"
,
"
#8FAC34
"
,
"
#98B333
"
];
const
color
=
treeColors
[
Math
.
floor
(
Math
.
random
()
*
3
)];
trees
.
push
({
x
,
color
});
}
function
generatePlatform
()
{
const
minimumGap
=
40
;
const
maximumGap
=
200
;
const
minimumWidth
=
20
;
const
maximumWidth
=
100
;
const
lastPlatform
=
platforms
[
platforms
.
length
-
1
];
let
furthestX
=
lastPlatform
.
x
+
lastPlatform
.
w
;
const
x
=
furthestX
+
minimumGap
+
Math
.
floor
(
Math
.
random
()
*
(
maximumGap
-
minimumGap
));
const
w
=
minimumWidth
+
Math
.
floor
(
Math
.
random
()
*
(
maximumWidth
-
minimumWidth
));
platforms
.
push
({
x
,
w
});
}
resetGame
();
// If space was pressed restart the game
window
.
addEventListener
(
"
keydown
"
,
function
(
event
)
{
if
(
event
.
key
==
"
"
)
{
event
.
preventDefault
();
resetGame
();
return
;
}
});
window
.
addEventListener
(
"
mousedown
"
,
function
(
event
)
{
if
(
phase
==
"
waiting
"
)
{
lastTimestamp
=
undefined
;
introductionElement
.
style
.
opacity
=
0
;
phase
=
"
stretching
"
;
window
.
requestAnimationFrame
(
animate
);
}
});
window
.
addEventListener
(
"
mouseup
"
,
function
(
event
)
{
if
(
phase
==
"
stretching
"
)
{
phase
=
"
turning
"
;
}
});
window
.
addEventListener
(
"
resize
"
,
function
(
event
)
{
canvas
.
width
=
window
.
innerWidth
;
canvas
.
height
=
window
.
innerHeight
;
draw
();
});
window
.
requestAnimationFrame
(
animate
);
// The main game loop
function
animate
(
timestamp
)
{
if
(
!
lastTimestamp
)
{
lastTimestamp
=
timestamp
;
window
.
requestAnimationFrame
(
animate
);
return
;
}
switch
(
phase
)
{
case
"
waiting
"
:
return
;
// Stop the loop
case
"
stretching
"
:
{
sticks
.
last
().
length
+=
(
timestamp
-
lastTimestamp
)
/
stretchingSpeed
;
break
;
}
case
"
turning
"
:
{
sticks
.
last
().
rotation
+=
(
timestamp
-
lastTimestamp
)
/
turningSpeed
;
if
(
sticks
.
last
().
rotation
>
90
)
{
sticks
.
last
().
rotation
=
90
;
const
[
nextPlatform
,
perfectHit
]
=
thePlatformTheStickHits
();
if
(
nextPlatform
)
{
// Increase score
score
+=
perfectHit
?
2
:
1
;
scoreElement
.
innerText
=
score
;
if
(
perfectHit
)
{
perfectElement
.
style
.
opacity
=
1
;
setTimeout
(()
=>
(
perfectElement
.
style
.
opacity
=
0
),
1000
);
}
generatePlatform
();
generateTree
();
generateTree
();
}
phase
=
"
walking
"
;
}
break
;
}
case
"
walking
"
:
{
heroX
+=
(
timestamp
-
lastTimestamp
)
/
walkingSpeed
;
const
[
nextPlatform
]
=
thePlatformTheStickHits
();
if
(
nextPlatform
)
{
const
maxHeroX
=
nextPlatform
.
x
+
nextPlatform
.
w
-
heroDistanceFromEdge
;
if
(
heroX
>
maxHeroX
)
{
heroX
=
maxHeroX
;
phase
=
"
transitioning
"
;
}
}
else
{
const
maxHeroX
=
sticks
.
last
().
x
+
sticks
.
last
().
length
+
heroWidth
;
if
(
heroX
>
maxHeroX
)
{
heroX
=
maxHeroX
;
phase
=
"
falling
"
;
}
}
break
;
}
case
"
transitioning
"
:
{
sceneOffset
+=
(
timestamp
-
lastTimestamp
)
/
transitioningSpeed
;
const
[
nextPlatform
]
=
thePlatformTheStickHits
();
if
(
sceneOffset
>
nextPlatform
.
x
+
nextPlatform
.
w
-
paddingX
)
{
// Add the next step
sticks
.
push
({
x
:
nextPlatform
.
x
+
nextPlatform
.
w
,
length
:
0
,
rotation
:
0
});
phase
=
"
waiting
"
;
}
break
;
}
case
"
falling
"
:
{
if
(
sticks
.
last
().
rotation
<
180
)
sticks
.
last
().
rotation
+=
(
timestamp
-
lastTimestamp
)
/
turningSpeed
;
heroY
+=
(
timestamp
-
lastTimestamp
)
/
fallingSpeed
;
const
maxHeroY
=
platformHeight
+
100
+
(
window
.
innerHeight
-
canvasHeight
)
/
2
;
if
(
heroY
>
maxHeroY
)
{
restartButton
.
style
.
display
=
"
block
"
;
return
;
}
break
;
}
default
:
throw
Error
(
"
Wrong phase
"
);
}
draw
();
window
.
requestAnimationFrame
(
animate
);
lastTimestamp
=
timestamp
;
}
function
thePlatformTheStickHits
()
{
if
(
sticks
.
last
().
rotation
!=
90
)
throw
Error
(
`Stick is
${
sticks
.
last
().
rotation
}
°`
);
const
stickFarX
=
sticks
.
last
().
x
+
sticks
.
last
().
length
;
const
platformTheStickHits
=
platforms
.
find
(
(
platform
)
=>
platform
.
x
<
stickFarX
&&
stickFarX
<
platform
.
x
+
platform
.
w
);
if
(
platformTheStickHits
&&
platformTheStickHits
.
x
+
platformTheStickHits
.
w
/
2
-
perfectAreaSize
/
2
<
stickFarX
&&
stickFarX
<
platformTheStickHits
.
x
+
platformTheStickHits
.
w
/
2
+
perfectAreaSize
/
2
)
return
[
platformTheStickHits
,
true
];
return
[
platformTheStickHits
,
false
];
}
function
draw
()
{
ctx
.
save
();
ctx
.
clearRect
(
0
,
0
,
window
.
innerWidth
,
window
.
innerHeight
);
drawBackground
();
ctx
.
translate
(
(
window
.
innerWidth
-
canvasWidth
)
/
2
-
sceneOffset
,
(
window
.
innerHeight
-
canvasHeight
)
/
2
);
// Draw scene
drawPlatforms
();
drawHero
();
drawSticks
();
// Restore transformation
ctx
.
restore
();
}
restartButton
.
addEventListener
(
"
click
"
,
function
(
event
)
{
event
.
preventDefault
();
resetGame
();
restartButton
.
style
.
display
=
"
none
"
;
});
function
drawPlatforms
()
{
platforms
.
forEach
(({
x
,
w
})
=>
{
// Draw platform
ctx
.
fillStyle
=
"
black
"
;
ctx
.
fillRect
(
x
,
canvasHeight
-
platformHeight
,
w
,
platformHeight
+
(
window
.
innerHeight
-
canvasHeight
)
/
2
);
if
(
sticks
.
last
().
x
<
x
)
{
ctx
.
fillStyle
=
"
red
"
;
ctx
.
fillRect
(
x
+
w
/
2
-
perfectAreaSize
/
2
,
canvasHeight
-
platformHeight
,
perfectAreaSize
,
perfectAreaSize
);
}
});
}
function
drawHero
()
{
ctx
.
save
();
ctx
.
fillStyle
=
"
black
"
;
ctx
.
translate
(
heroX
-
heroWidth
/
2
,
heroY
+
canvasHeight
-
platformHeight
-
heroHeight
/
2
);
// Body
drawRoundedRect
(
-
heroWidth
/
2
,
-
heroHeight
/
2
,
heroWidth
,
heroHeight
-
4
,
5
);
// Legs
const
legDistance
=
5
;
ctx
.
beginPath
();
ctx
.
arc
(
legDistance
,
11.5
,
3
,
0
,
Math
.
PI
*
2
,
false
);
ctx
.
fill
();
ctx
.
beginPath
();
ctx
.
arc
(
-
legDistance
,
11.5
,
3
,
0
,
Math
.
PI
*
2
,
false
);
ctx
.
fill
();
// Eye
ctx
.
beginPath
();
ctx
.
fillStyle
=
"
white
"
;
ctx
.
arc
(
5
,
-
7
,
3
,
0
,
Math
.
PI
*
2
,
false
);
ctx
.
fill
();
// Band
ctx
.
fillStyle
=
"
red
"
;
ctx
.
fillRect
(
-
heroWidth
/
2
-
1
,
-
12
,
heroWidth
+
2
,
4.5
);
ctx
.
beginPath
();
ctx
.
moveTo
(
-
9
,
-
14.5
);
ctx
.
lineTo
(
-
17
,
-
18.5
);
ctx
.
lineTo
(
-
14
,
-
8.5
);
ctx
.
fill
();
ctx
.
beginPath
();
ctx
.
moveTo
(
-
10
,
-
10.5
);
ctx
.
lineTo
(
-
15
,
-
3.5
);
ctx
.
lineTo
(
-
5
,
-
7
);
ctx
.
fill
();
ctx
.
restore
();
}
function
drawRoundedRect
(
x
,
y
,
width
,
height
,
radius
)
{
ctx
.
beginPath
();
ctx
.
moveTo
(
x
,
y
+
radius
);
ctx
.
lineTo
(
x
,
y
+
height
-
radius
);
ctx
.
arcTo
(
x
,
y
+
height
,
x
+
radius
,
y
+
height
,
radius
);
ctx
.
lineTo
(
x
+
width
-
radius
,
y
+
height
);
ctx
.
arcTo
(
x
+
width
,
y
+
height
,
x
+
width
,
y
+
height
-
radius
,
radius
);
ctx
.
lineTo
(
x
+
width
,
y
+
radius
);
ctx
.
arcTo
(
x
+
width
,
y
,
x
+
width
-
radius
,
y
,
radius
);
ctx
.
lineTo
(
x
+
radius
,
y
);
ctx
.
arcTo
(
x
,
y
,
x
,
y
+
radius
,
radius
);
ctx
.
fill
();
}
function
drawSticks
()
{
sticks
.
forEach
((
stick
)
=>
{
ctx
.
save
();
ctx
.
translate
(
stick
.
x
,
canvasHeight
-
platformHeight
);
ctx
.
rotate
((
Math
.
PI
/
180
)
*
stick
.
rotation
);
// Draw stick
ctx
.
beginPath
();
ctx
.
lineWidth
=
2
;
ctx
.
moveTo
(
0
,
0
);
ctx
.
lineTo
(
0
,
-
stick
.
length
);
ctx
.
stroke
();
// Restore transformations
ctx
.
restore
();
});
}
function
drawBackground
()
{
// Draw sky
var
gradient
=
ctx
.
createLinearGradient
(
0
,
0
,
0
,
window
.
innerHeight
);
gradient
.
addColorStop
(
0
,
"
#BBD691
"
);
gradient
.
addColorStop
(
1
,
"
#FEF1E1
"
);
ctx
.
fillStyle
=
gradient
;
ctx
.
fillRect
(
0
,
0
,
window
.
innerWidth
,
window
.
innerHeight
);
// Draw hills
drawHill
(
hill1BaseHeight
,
hill1Amplitude
,
hill1Stretch
,
"
#95C629
"
);
drawHill
(
hill2BaseHeight
,
hill2Amplitude
,
hill2Stretch
,
"
#659F1C
"
);
// Draw trees
trees
.
forEach
((
tree
)
=>
drawTree
(
tree
.
x
,
tree
.
color
));
}
function
drawHill
(
baseHeight
,
amplitude
,
stretch
,
color
)
{
ctx
.
beginPath
();
ctx
.
moveTo
(
0
,
window
.
innerHeight
);
ctx
.
lineTo
(
0
,
getHillY
(
0
,
baseHeight
,
amplitude
,
stretch
));
for
(
let
i
=
0
;
i
<
window
.
innerWidth
;
i
++
)
{
ctx
.
lineTo
(
i
,
getHillY
(
i
,
baseHeight
,
amplitude
,
stretch
));
}
ctx
.
lineTo
(
window
.
innerWidth
,
window
.
innerHeight
);
ctx
.
fillStyle
=
color
;
ctx
.
fill
();
}
function
drawTree
(
x
,
color
)
{
ctx
.
save
();
ctx
.
translate
(
(
-
sceneOffset
*
backgroundSpeedMultiplier
+
x
)
*
hill1Stretch
,
getTreeY
(
x
,
hill1BaseHeight
,
hill1Amplitude
)
);
const
treeTrunkHeight
=
5
;
const
treeTrunkWidth
=
2
;
const
treeCrownHeight
=
25
;
const
treeCrownWidth
=
10
;
// Draw trunk
ctx
.
fillStyle
=
"
#7D833C
"
;
ctx
.
fillRect
(
-
treeTrunkWidth
/
2
,
-
treeTrunkHeight
,
treeTrunkWidth
,
treeTrunkHeight
);
// Draw crown
ctx
.
beginPath
();
ctx
.
moveTo
(
-
treeCrownWidth
/
2
,
-
treeTrunkHeight
);
ctx
.
lineTo
(
0
,
-
(
treeTrunkHeight
+
treeCrownHeight
));
ctx
.
lineTo
(
treeCrownWidth
/
2
,
-
treeTrunkHeight
);
ctx
.
fillStyle
=
color
;
ctx
.
fill
();
ctx
.
restore
();
}
function
getHillY
(
windowX
,
baseHeight
,
amplitude
,
stretch
)
{
const
sineBaseY
=
window
.
innerHeight
-
baseHeight
;
return
(
Math
.
sinus
((
sceneOffset
*
backgroundSpeedMultiplier
+
windowX
)
*
stretch
)
*
amplitude
+
sineBaseY
);
}
function
getTreeY
(
x
,
baseHeight
,
amplitude
)
{
const
sineBaseY
=
window
.
innerHeight
-
baseHeight
;
return
Math
.
sinus
(
x
)
*
amplitude
+
sineBaseY
;
}
ninja1.js
0 → 100644
浏览文件 @
eb1a2959
//coming soon
\ No newline at end of file
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录