started platformer demo, added features back to physics system
This commit is contained in:
parent
681d63f202
commit
eeaf73bab4
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -1,2 +1,12 @@
|
|||
# Exclude node modules
|
||||
node_modules
|
||||
dist/
|
||||
|
||||
# Exclude the compiled project
|
||||
dist/*
|
||||
|
||||
# Include the demo_assets folder
|
||||
!dist/demo_assets/
|
||||
|
||||
### IF YOU ARE MAKING A PROJECT, YOU MAY WANT TO UNCOMMENT THIS LINE ###
|
||||
# !dist/assets/
|
||||
|
||||
|
|
BIN
dist/demo_assets/images/platformer_background.png
vendored
Normal file
BIN
dist/demo_assets/images/platformer_background.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 4.7 KiB |
BIN
dist/demo_assets/images/wolfie2d_text.png
vendored
Normal file
BIN
dist/demo_assets/images/wolfie2d_text.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 701 B |
BIN
dist/demo_assets/sounds/jump.wav
vendored
Normal file
BIN
dist/demo_assets/sounds/jump.wav
vendored
Normal file
Binary file not shown.
27
dist/demo_assets/spritesheets/platformer/player.json
vendored
Normal file
27
dist/demo_assets/spritesheets/platformer/player.json
vendored
Normal file
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"name": "PlatformerPlayer",
|
||||
"spriteSheetImage": "player.png",
|
||||
"spriteWidth": 16,
|
||||
"spriteHeight": 16,
|
||||
"columns": 5,
|
||||
"rows": 1,
|
||||
"durationType": "time",
|
||||
"animations": [
|
||||
{
|
||||
"name": "IDLE",
|
||||
"frames": [ {"index": 0, "duration": 1} ]
|
||||
},
|
||||
{
|
||||
"name": "WALK",
|
||||
"frames": [ {"index": 0, "duration": 16}, {"index": 1, "duration": 16}, {"index": 2, "duration": 16}, {"index": 3, "duration": 16} ]
|
||||
},
|
||||
{
|
||||
"name": "JUMP",
|
||||
"frames":[ {"index": 4, "duration": 32}]
|
||||
},
|
||||
{
|
||||
"name": "FALL",
|
||||
"frames":[ {"index": 4, "duration": 32}]
|
||||
}
|
||||
]
|
||||
}
|
BIN
dist/demo_assets/spritesheets/platformer/player.png
vendored
Normal file
BIN
dist/demo_assets/spritesheets/platformer/player.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 268 B |
453
dist/demo_assets/tilemaps/platformer/platformer.json
vendored
Normal file
453
dist/demo_assets/tilemaps/platformer/platformer.json
vendored
Normal file
|
@ -0,0 +1,453 @@
|
|||
{ "compressionlevel":-1,
|
||||
"editorsettings":
|
||||
{
|
||||
"export":
|
||||
{
|
||||
"format":"json",
|
||||
"target":"platformer.json"
|
||||
}
|
||||
},
|
||||
"height":20,
|
||||
"infinite":false,
|
||||
"layers":[
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, 44, 44, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 0, 44, 44, 44, 44, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 0, 43, 0, 44, 44, 44, 44, 44, 44, 0, 44, 44, 44, 44, 44, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 35, 36, 0, 36, 36, 36, 36, 36, 36, 36, 36, 36, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 0, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 54, 55, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 45, 0, 43, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 44, 62, 63, 44, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 43, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":20,
|
||||
"id":2,
|
||||
"name":"Background",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"Collidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"Depth",
|
||||
"type":"int",
|
||||
"value":0
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":64,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 19, 20, 20, 20, 8, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 11, 12, 10, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 10, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 12, 12, 12, 12, 12, 12, 12, 9, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 16, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 12, 9, 12, 12, 12, 12, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 12, 12, 12, 7, 20, 20, 20, 20, 20, 20, 8, 12, 12, 12, 12, 10, 12, 12, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, 29, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 9, 16, 12, 12, 13, 0, 0, 0, 0, 0, 0, 11, 12, 12, 12, 12, 12, 12, 9, 12, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 17, 19, 20, 20, 20, 20, 13, 0, 0, 0, 0, 0, 0, 11, 20, 20, 20, 20, 20, 20, 20, 8, 12, 9, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 22, 0, 0, 0, 0, 0, 0, 0, 11, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 12, 12, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 2, 2, 2, 2, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 11, 10, 13, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 0, 0, 0, 0, 0, 0, 11, 12, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 2, 2, 2, 2, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 12, 13, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, 10, 12, 12, 12, 12, 12, 12, 10, 15, 4, 4, 4, 4, 4, 4, 4, 4],
|
||||
"height":20,
|
||||
"id":1,
|
||||
"name":"Main",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"Collidable",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"Depth",
|
||||
"type":"int",
|
||||
"value":1
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":64,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"draworder":"topdown",
|
||||
"id":4,
|
||||
"name":"Coins",
|
||||
"objects":[
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":2,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":256,
|
||||
"y":272
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":3,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":272,
|
||||
"y":272
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":4,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":368,
|
||||
"y":288
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":5,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":384,
|
||||
"y":288
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":6,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":400,
|
||||
"y":288
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":7,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":688,
|
||||
"y":272
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":8,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":688,
|
||||
"y":288
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":9,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":688,
|
||||
"y":304
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":10,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":784,
|
||||
"y":256
|
||||
},
|
||||
{
|
||||
"gid":25,
|
||||
"height":16,
|
||||
"id":11,
|
||||
"name":"",
|
||||
"properties":[
|
||||
{
|
||||
"name":"Group",
|
||||
"type":"string",
|
||||
"value":"Coins"
|
||||
},
|
||||
{
|
||||
"name":"HasPhysics",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
},
|
||||
{
|
||||
"name":"IsCollidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"IsTrigger",
|
||||
"type":"bool",
|
||||
"value":true
|
||||
}],
|
||||
"rotation":0,
|
||||
"type":"",
|
||||
"visible":true,
|
||||
"width":16,
|
||||
"x":832,
|
||||
"y":256
|
||||
}],
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"Depth",
|
||||
"type":"int",
|
||||
"value":1
|
||||
}],
|
||||
"type":"objectgroup",
|
||||
"visible":true,
|
||||
"x":0,
|
||||
"y":0
|
||||
},
|
||||
{
|
||||
"data":[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
|
||||
"height":20,
|
||||
"id":3,
|
||||
"name":"Foreground",
|
||||
"opacity":1,
|
||||
"properties":[
|
||||
{
|
||||
"name":"Collidable",
|
||||
"type":"bool",
|
||||
"value":false
|
||||
},
|
||||
{
|
||||
"name":"Depth",
|
||||
"type":"int",
|
||||
"value":2
|
||||
}],
|
||||
"type":"tilelayer",
|
||||
"visible":true,
|
||||
"width":64,
|
||||
"x":0,
|
||||
"y":0
|
||||
}],
|
||||
"nextlayerid":5,
|
||||
"nextobjectid":14,
|
||||
"orientation":"orthogonal",
|
||||
"renderorder":"right-down",
|
||||
"tiledversion":"1.3.4",
|
||||
"tileheight":16,
|
||||
"tilesets":[
|
||||
{
|
||||
"columns":8,
|
||||
"firstgid":1,
|
||||
"image":"platformer.png",
|
||||
"imageheight":128,
|
||||
"imagewidth":128,
|
||||
"margin":0,
|
||||
"name":"platformer_tileset",
|
||||
"spacing":0,
|
||||
"tilecount":64,
|
||||
"tileheight":16,
|
||||
"tilewidth":16
|
||||
}],
|
||||
"tilewidth":16,
|
||||
"type":"map",
|
||||
"version":1.2,
|
||||
"width":64
|
||||
}
|
BIN
dist/demo_assets/tilemaps/platformer/platformer.png
vendored
Normal file
BIN
dist/demo_assets/tilemaps/platformer/platformer.png
vendored
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
49
src/Platformer.ts
Normal file
49
src/Platformer.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
import PlayerController from "./PlatformerPlayerController";
|
||||
import Vec2 from "./Wolfie2D/DataTypes/Vec2";
|
||||
import AnimatedSprite from "./Wolfie2D/Nodes/Sprites/AnimatedSprite";
|
||||
import Scene from "./Wolfie2D/Scene/Scene";
|
||||
|
||||
export default class Platformer extends Scene {
|
||||
private player: AnimatedSprite;
|
||||
|
||||
// Load any assets you will need for the project here
|
||||
loadScene(){
|
||||
// Load the player spritesheet
|
||||
this.load.spritesheet("player", "demo_assets/spritesheets/platformer/player.json");
|
||||
|
||||
// Load the tilemap
|
||||
this.load.tilemap("platformer", "demo_assets/tilemaps/platformer/platformer.json");
|
||||
|
||||
// Load the background image
|
||||
this.load.image("background", "demo_assets/images/platformer_background.png");
|
||||
|
||||
// Load a jump sound
|
||||
this.load.audio("jump", "demo_assets/sounds/jump.wav");
|
||||
}
|
||||
|
||||
// Add GameObjects to the scene
|
||||
startScene(){
|
||||
this.addLayer("primary", 1);
|
||||
|
||||
// Add the player in the starting position
|
||||
this.player = this.add.animatedSprite("player", "primary");
|
||||
this.player.animation.play("IDLE");
|
||||
this.player.position.set(3*16, 18*16);
|
||||
|
||||
// Add physics so the player can move
|
||||
this.player.addPhysics();
|
||||
this.player.addAI(PlayerController, {jumpSoundKey: "jump"});
|
||||
|
||||
// Size of the tilemap is 64x20. Tile size is 16x16
|
||||
this.viewport.setBounds(0, 0, 64*16, 20*16);
|
||||
this.viewport.follow(this.player);
|
||||
|
||||
// Add the tilemap. Top left corner is (0, 0) by default
|
||||
this.add.tilemap("platformer");
|
||||
|
||||
// Add a background to the scene
|
||||
this.addParallaxLayer("bg", new Vec2(0.5, 1), -1);
|
||||
let bg = this.add.sprite("background", "bg");
|
||||
bg.position.set(bg.size.x/2, bg.size.y/2);
|
||||
}
|
||||
}
|
59
src/PlatformerPlayerController.ts
Normal file
59
src/PlatformerPlayerController.ts
Normal file
|
@ -0,0 +1,59 @@
|
|||
import AI from "./Wolfie2D/DataTypes/Interfaces/AI";
|
||||
import Emitter from "./Wolfie2D/Events/Emitter";
|
||||
import GameEvent from "./Wolfie2D/Events/GameEvent";
|
||||
import { GameEventType } from "./Wolfie2D/Events/GameEventType";
|
||||
import Input from "./Wolfie2D/Input/Input";
|
||||
import AnimatedSprite from "./Wolfie2D/Nodes/Sprites/AnimatedSprite";
|
||||
|
||||
export default class PlayerController implements AI {
|
||||
protected owner: AnimatedSprite;
|
||||
protected jumpSoundKey: string;
|
||||
protected emitter: Emitter;
|
||||
|
||||
initializeAI(owner: AnimatedSprite, options: Record<string, any>): void {
|
||||
this.owner = owner;
|
||||
this.jumpSoundKey = options.jumpSoundKey;
|
||||
this.emitter = new Emitter();
|
||||
}
|
||||
|
||||
handleEvent(event: GameEvent): void {
|
||||
// Do nothing for now
|
||||
}
|
||||
|
||||
update(deltaT: number): void {
|
||||
// Get the direction from key presses
|
||||
const x = (Input.isPressed("left") ? -1 : 0) + (Input.isPressed("right") ? 1 : 0);
|
||||
|
||||
// Get last velocity and override x
|
||||
const velocity = this.owner.getLastVelocity();
|
||||
velocity.x = x * 100 * deltaT;
|
||||
|
||||
// Check for jump condition
|
||||
if(this.owner.onGround && Input.isJustPressed("jump")){
|
||||
// We are jumping
|
||||
velocity.y = -250*deltaT;
|
||||
|
||||
// Loop our jump animation
|
||||
this.owner.animation.play("JUMP", true);
|
||||
|
||||
// Play the jump sound
|
||||
this.emitter.fireEvent(GameEventType.PLAY_SOUND, {key: this.jumpSoundKey, loop: false});
|
||||
} else {
|
||||
velocity.y += 10*deltaT;
|
||||
}
|
||||
|
||||
if(this.owner.onGround && !Input.isJustPressed("jump")){
|
||||
// If we're on the ground, but aren't jumping, show walk animation
|
||||
if(velocity.x === 0){
|
||||
this.owner.animation.playIfNotAlready("IDLE", true);
|
||||
} else {
|
||||
this.owner.animation.playIfNotAlready("WALK", true);
|
||||
}
|
||||
}
|
||||
|
||||
// If we're walking left, flip the sprite
|
||||
this.owner.invertX = velocity.x < 0;
|
||||
|
||||
this.owner.move(velocity);
|
||||
}
|
||||
}
|
18
src/Wolfie2D/AI/ControllerAI.ts
Normal file
18
src/Wolfie2D/AI/ControllerAI.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import AI from "../DataTypes/Interfaces/AI";
|
||||
import GameEvent from "../Events/GameEvent";
|
||||
import GameNode from "../Nodes/GameNode";
|
||||
|
||||
/**
|
||||
* A very basic AI class that just runs a function every update
|
||||
*/
|
||||
export default class ControllerAI implements AI {
|
||||
protected owner: GameNode;
|
||||
|
||||
initializeAI(owner: GameNode, options: Record<string, any>): void {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
handleEvent(event: GameEvent): void {}
|
||||
|
||||
update(deltaT: number): void {}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import AI from "../DataTypes/Interfaces/AI";
|
||||
import StateMachine from "../DataTypes/State/StateMachine";
|
||||
import GameEvent from "../Events/GameEvent";
|
||||
import GameNode from "../Nodes/GameNode";
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import GameEvent from "../../Events/GameEvent";
|
||||
import GameNode from "../../Nodes/GameNode";
|
||||
import Actor from "./Actor";
|
||||
import Updateable from "./Updateable";
|
||||
|
||||
/**
|
||||
|
@ -7,4 +9,7 @@ import Updateable from "./Updateable";
|
|||
export default interface AI extends Updateable {
|
||||
/** Initializes the AI with the actor and any additional config */
|
||||
initializeAI(owner: GameNode, options: Record<string, any>): void;
|
||||
|
||||
/** Handles events from the Actor */
|
||||
handleEvent(event: GameEvent): void;
|
||||
}
|
|
@ -1,4 +1,7 @@
|
|||
import Physical from "../Interfaces/Physical";
|
||||
import AABB from "../Shapes/AABB";
|
||||
import Vec2 from "../Vec2";
|
||||
import Hit from "./Hit";
|
||||
|
||||
/**
|
||||
* A class that contains the area of overlap of two colliding objects to allow for sorting by the physics system.
|
||||
|
@ -6,16 +9,32 @@ import AABB from "../Shapes/AABB";
|
|||
export default class AreaCollision {
|
||||
/** The area of the overlap for the colliding objects */
|
||||
area: number;
|
||||
|
||||
/** The AABB of the other collider in this collision */
|
||||
collider: AABB;
|
||||
|
||||
|
||||
/** Type of the collision */
|
||||
type: string;
|
||||
|
||||
/** Ther other object in the collision */
|
||||
other: Physical;
|
||||
|
||||
/** The tile, if this was a tilemap collision */
|
||||
tile: Vec2;
|
||||
|
||||
/** The physics hit for this object */
|
||||
hit: Hit;
|
||||
|
||||
/**
|
||||
* Creates a new AreaCollision object
|
||||
* @param area The area of the collision
|
||||
* @param collider The other collider
|
||||
*/
|
||||
constructor(area: number, collider: AABB){
|
||||
constructor(area: number, collider: AABB, other: Physical, type: string, tile: Vec2){
|
||||
this.area = area;
|
||||
this.collider = collider;
|
||||
this.collider = collider;
|
||||
this.other = other;
|
||||
this.type = type;
|
||||
this.tile = tile;
|
||||
}
|
||||
}
|
|
@ -146,7 +146,13 @@ export default class AABB extends Shape {
|
|||
// We hit on the left or right size
|
||||
hit.normal.x = -signX;
|
||||
hit.normal.y = 0;
|
||||
} else if(Math.abs(tnearx - tneary) < 0.0001){
|
||||
// We hit on the corner
|
||||
hit.normal.x = -signX;
|
||||
hit.normal.y = -signY;
|
||||
hit.normal.normalize();
|
||||
} else {
|
||||
// We hit on the top or bottom
|
||||
hit.normal.x = 0;
|
||||
hit.normal.y = -signY;
|
||||
}
|
||||
|
@ -190,6 +196,70 @@ export default class AABB extends Shape {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether these AABBs are JUST touching - not overlapping.
|
||||
* Vec2.x is -1 if the other is to the left, 1 if to the right.
|
||||
* Likewise, Vec2.y is -1 if the other is on top, 1 if on bottom.
|
||||
* @param other The other AABB to check
|
||||
* @returns The collision sides stored in a Vec2 if the AABBs are touching, null otherwise
|
||||
*/
|
||||
touchesAABB(other: AABB): Vec2 {
|
||||
let dx = other.x - this.x;
|
||||
let px = this.hw + other.hw - Math.abs(dx);
|
||||
|
||||
let dy = other.y - this.y;
|
||||
let py = this.hh + other.hh - Math.abs(dy);
|
||||
|
||||
// If one axis is just touching and the other is overlapping, true
|
||||
if((px === 0 && py >= 0) || (py === 0 && px >= 0)){
|
||||
let ret = new Vec2();
|
||||
|
||||
if(px === 0){
|
||||
ret.x = other.x < this.x ? -1 : 1;
|
||||
}
|
||||
|
||||
if(py === 0){
|
||||
ret.y = other.y < this.y ? -1 : 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether these AABBs are JUST touching - not overlapping.
|
||||
* Also, if they are only touching corners, they are considered not touching.
|
||||
* Vec2.x is -1 if the other is to the left, 1 if to the right.
|
||||
* Likewise, Vec2.y is -1 if the other is on top, 1 if on bottom.
|
||||
* @param other The other AABB to check
|
||||
* @returns The side of the touch, stored as a Vec2, or null if there is no touch
|
||||
*/
|
||||
touchesAABBWithoutCorners(other: AABB): Vec2 {
|
||||
let dx = other.x - this.x;
|
||||
let px = this.hw + other.hw - Math.abs(dx);
|
||||
|
||||
let dy = other.y - this.y;
|
||||
let py = this.hh + other.hh - Math.abs(dy);
|
||||
|
||||
// If one axis is touching, and the other is strictly overlapping
|
||||
if((px === 0 && py > 0) || (py === 0 && px > 0)){
|
||||
let ret = new Vec2();
|
||||
|
||||
if(px === 0){
|
||||
ret.x = other.x < this.x ? -1 : 1;
|
||||
} else {
|
||||
ret.y = other.y < this.y ? -1 : 1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the area of the overlap between this AABB and another
|
||||
* @param other The other AABB
|
||||
|
|
|
@ -116,24 +116,14 @@ export default class StateMachine implements Updateable {
|
|||
* Handles input. This happens at the very beginning of this state machine's update cycle.
|
||||
* @param event The game event to process
|
||||
*/
|
||||
handleInput(event: GameEvent): void {
|
||||
this.currentState.handleInput(event);
|
||||
handleEvent(event: GameEvent): void {
|
||||
if(this.active){
|
||||
this.currentState.handleInput(event);
|
||||
}
|
||||
}
|
||||
|
||||
// @implemented
|
||||
update(deltaT: number): void {
|
||||
// If the state machine isn't currently active, ignore all events and don't update
|
||||
if(!this.active){
|
||||
this.receiver.ignoreEvents();
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle input from all events
|
||||
while(this.receiver.hasNextEvent()){
|
||||
let event = this.receiver.getNextEvent();
|
||||
this.handleInput(event);
|
||||
}
|
||||
|
||||
// Delegate the update to the current state
|
||||
this.currentState.update(deltaT);
|
||||
}
|
||||
|
|
|
@ -62,6 +62,9 @@ export default class Debug {
|
|||
* @param color The color of the box to draw
|
||||
*/
|
||||
static drawBox(center: Vec2, halfSize: Vec2, filled: boolean, color: Color): void {
|
||||
let alpha = this.debugRenderingContext.globalAlpha;
|
||||
this.debugRenderingContext.globalAlpha = color.a;
|
||||
|
||||
if(filled){
|
||||
this.debugRenderingContext.fillStyle = color.toString();
|
||||
this.debugRenderingContext.fillRect(center.x - halfSize.x, center.y - halfSize.y, halfSize.x*2, halfSize.y*2);
|
||||
|
@ -71,6 +74,8 @@ export default class Debug {
|
|||
this.debugRenderingContext.strokeStyle = color.toString();
|
||||
this.debugRenderingContext.strokeRect(center.x - halfSize.x, center.y - halfSize.y, halfSize.x*2, halfSize.y*2);
|
||||
}
|
||||
|
||||
this.debugRenderingContext.globalAlpha = alpha;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -70,8 +70,8 @@ export default class Game {
|
|||
this.DEBUG_CANVAS = <HTMLCanvasElement>document.getElementById("debug-canvas");
|
||||
|
||||
// Give the canvas a size and get the rendering context
|
||||
this.WIDTH = this.gameOptions.viewportSize.x;
|
||||
this.HEIGHT = this.gameOptions.viewportSize.y;
|
||||
this.WIDTH = this.gameOptions.canvasSize.x;
|
||||
this.HEIGHT = this.gameOptions.canvasSize.y;
|
||||
|
||||
// For now, just hard code a canvas renderer. We can do this with options later
|
||||
this.renderingManager = new CanvasRenderer();
|
||||
|
@ -89,8 +89,8 @@ export default class Game {
|
|||
}
|
||||
|
||||
// Size the viewport to the game canvas
|
||||
const viewportSize = new Vec2(this.WIDTH, this.HEIGHT);
|
||||
this.viewport = new Viewport(viewportSize.scaled(0.5), viewportSize);
|
||||
const canvasSize = new Vec2(this.WIDTH, this.HEIGHT);
|
||||
this.viewport = new Viewport(canvasSize, this.gameOptions.zoomLevel);
|
||||
|
||||
// Initialize all necessary game subsystems
|
||||
this.eventQueue = EventQueue.getInstance();
|
||||
|
|
|
@ -3,7 +3,10 @@
|
|||
/** The options for initializing the @reference[GameLoop] */
|
||||
export default class GameOptions {
|
||||
/** The size of the viewport */
|
||||
viewportSize: {x: number, y: number};
|
||||
canvasSize: {x: number, y: number};
|
||||
|
||||
/* The default level of zoom */
|
||||
zoomLevel: number;
|
||||
|
||||
/** The color to clear the canvas to each frame */
|
||||
clearColor: {r: number, g: number, b: number}
|
||||
|
@ -25,7 +28,8 @@ export default class GameOptions {
|
|||
static parse(options: Record<string, any>): GameOptions {
|
||||
let gOpt = new GameOptions();
|
||||
|
||||
gOpt.viewportSize = options.viewportSize ? options.viewportSize : {x: 800, y: 600};
|
||||
gOpt.canvasSize = options.canvasSize ? options.canvasSize : {x: 800, y: 600};
|
||||
gOpt.zoomLevel = options.zoomLevel ? options.zoomLevel : 1;
|
||||
gOpt.clearColor = options.clearColor ? options.clearColor : {r: 255, g: 255, b: 255};
|
||||
gOpt.inputs = options.inputs ? options.inputs : [];
|
||||
gOpt.showDebug = !!options.showDebug;
|
||||
|
|
|
@ -101,8 +101,7 @@ export default abstract class CanvasNode extends GameNode implements Region {
|
|||
|
||||
// @implemented
|
||||
debugRender(): void {
|
||||
Debug.drawBox(this.relativePosition, this.sizeWithZoom, false, Color.BLUE);
|
||||
super.debugRender();
|
||||
let color = this.isColliding ? Color.RED : Color.GREEN;
|
||||
Debug.drawBox(this.relativePosition, this.sizeWithZoom, false, color);
|
||||
}
|
||||
}
|
|
@ -31,12 +31,12 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
|
|||
private _id: number;
|
||||
|
||||
/*---------- PHYSICAL ----------*/
|
||||
hasPhysics: boolean;
|
||||
moving: boolean;
|
||||
onGround: boolean;
|
||||
onWall: boolean;
|
||||
onCeiling: boolean;
|
||||
active: boolean;
|
||||
hasPhysics: boolean = false;
|
||||
moving: boolean = false;
|
||||
onGround: boolean = false;
|
||||
onWall: boolean = false;
|
||||
onCeiling: boolean = false;
|
||||
active: boolean = false;
|
||||
collisionShape: Shape;
|
||||
colliderOffset: Vec2;
|
||||
isStatic: boolean;
|
||||
|
@ -97,10 +97,19 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
|
|||
}
|
||||
|
||||
get relativePosition(): Vec2 {
|
||||
return this.inRelativeCoordinates(this.position);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a point to coordinates relative to the zoom and origin of this node
|
||||
* @param point The point to conver
|
||||
* @returns A new Vec2 representing the point in relative coordinates
|
||||
*/
|
||||
inRelativeCoordinates(point: Vec2): Vec2 {
|
||||
let origin = this.scene.getViewTranslation(this);
|
||||
let zoom = this.scene.getViewScale();
|
||||
|
||||
return this.position.clone().sub(origin).scale(zoom);
|
||||
return point.clone().sub(origin).scale(zoom);
|
||||
}
|
||||
|
||||
/*---------- UNIQUE ----------*/
|
||||
|
@ -132,7 +141,6 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
|
|||
* @param velocity The velocity with which the object will move.
|
||||
*/
|
||||
finishMove(): void {
|
||||
console.log("finish");
|
||||
this.moving = false;
|
||||
this.position.add(this._velocity);
|
||||
if(this.pathfinding){
|
||||
|
@ -307,22 +315,35 @@ export default abstract class GameNode implements Positioned, Unique, Updateable
|
|||
* @param deltaT The timestep of the update.
|
||||
*/
|
||||
update(deltaT: number): void {
|
||||
// Defer event handling to AI.
|
||||
while(this.receiver.hasNextEvent()){
|
||||
this._ai.handleEvent(this.receiver.getNextEvent());
|
||||
}
|
||||
|
||||
// Update our tweens
|
||||
this.tweens.update(deltaT);
|
||||
}
|
||||
|
||||
// @implemented
|
||||
debugRender(): void {
|
||||
let color = this.isColliding ? Color.RED : Color.GREEN;
|
||||
Debug.drawPoint(this.relativePosition, color);
|
||||
// Draw the position of this GameNode
|
||||
Debug.drawPoint(this.relativePosition, Color.BLUE);
|
||||
|
||||
// If velocity is not zero, draw a vector for it
|
||||
if(this._velocity && !this._velocity.isZero()){
|
||||
Debug.drawRay(this.relativePosition, this._velocity.clone().scaleTo(20).add(this.relativePosition), color);
|
||||
Debug.drawRay(this.relativePosition, this._velocity.clone().scaleTo(20).add(this.relativePosition), Color.BLUE);
|
||||
}
|
||||
|
||||
// If this has a collider, draw it
|
||||
if(this.isCollidable && this.collisionShape){
|
||||
Debug.drawBox(this.collisionShape.center, this.collisionShape.halfSize, false, Color.RED);
|
||||
if(this.hasPhysics && this.collisionShape){
|
||||
let color = this.isColliding ? Color.RED : Color.GREEN;
|
||||
|
||||
if(this.isTrigger){
|
||||
color = Color.PURPLE;
|
||||
}
|
||||
|
||||
color.a = 0.2;
|
||||
Debug.drawBox(this.inRelativeCoordinates(this.collisionShape.center), this.collisionShape.halfSize.scaled(this.scene.getViewScale()), true, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,7 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
|||
node.onCeiling = false;
|
||||
node.onWall = false;
|
||||
node.collidedWithTilemap = false;
|
||||
node.isColliding = false;
|
||||
|
||||
// Update the swept shapes of each node
|
||||
if(node.moving){
|
||||
|
@ -110,7 +111,7 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
|||
let area = node.sweptRect.overlapArea(collider);
|
||||
if(area > 0){
|
||||
// We had a collision
|
||||
overlaps.push(new AreaCollision(area, collider));
|
||||
overlaps.push(new AreaCollision(area, collider, other, "GameNode", null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -120,7 +121,7 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
|||
let area = node.sweptRect.overlapArea(collider);
|
||||
if(area > 0){
|
||||
// We had a collision
|
||||
overlaps.push(new AreaCollision(area, collider));
|
||||
overlaps.push(new AreaCollision(area, collider, other, "GameNode", null));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,21 +136,27 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
|||
// Sort the overlaps by area
|
||||
overlaps = overlaps.sort((a, b) => b.area - a.area);
|
||||
|
||||
// Keep track of hits to use later
|
||||
let hits = [];
|
||||
|
||||
/*---------- RESOLUTION PHASE ----------*/
|
||||
// For every overlap, determine if we need to collide with it and when
|
||||
for(let other of overlaps){
|
||||
for(let overlap of overlaps){
|
||||
// Do a swept line test on the static AABB with this AABB size as padding (this is basically using a minkowski sum!)
|
||||
// Start the sweep at the position of this node with a delta of _velocity
|
||||
const point = node.collisionShape.center;
|
||||
const delta = node._velocity;
|
||||
const padding = node.collisionShape.halfSize;
|
||||
const otherAABB = other.collider;
|
||||
const otherAABB = overlap.collider;
|
||||
|
||||
|
||||
const hit = otherAABB.intersectSegment(node.collisionShape.center, node._velocity, node.collisionShape.halfSize);
|
||||
|
||||
overlap.hit = hit;
|
||||
|
||||
if(hit !== null){
|
||||
hits.push(hit);
|
||||
|
||||
// We got a hit, resolve with the time inside of the hit
|
||||
let tnearx = hit.nearTimes.x;
|
||||
let tneary = hit.nearTimes.y;
|
||||
|
@ -164,11 +171,39 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
|||
|
||||
|
||||
if(hit.nearTimes.x >= 0 && hit.nearTimes.x < 1){
|
||||
node._velocity.x = node._velocity.x * tnearx;
|
||||
// Any tilemap objects that made it here are collidable
|
||||
if(overlap.type === "Tilemap" || overlap.other.isCollidable){
|
||||
node._velocity.x = node._velocity.x * tnearx;
|
||||
node.isColliding = true;
|
||||
}
|
||||
}
|
||||
|
||||
if(hit.nearTimes.y >= 0 && hit.nearTimes.y < 1){
|
||||
node._velocity.y = node._velocity.y * tneary;
|
||||
// Any tilemap objects that made it here are collidable
|
||||
if(overlap.type === "Tilemap" || overlap.other.isCollidable){
|
||||
node._velocity.y = node._velocity.y * tneary;
|
||||
node.isColliding = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Check if we ended up on the ground, ceiling or wall
|
||||
for(let overlap of overlaps){
|
||||
let collisionSide = overlap.collider.touchesAABBWithoutCorners(node.collisionShape.getBoundingRect());
|
||||
if(collisionSide !== null){
|
||||
// If we touch, not including corner cases, check the collision normal
|
||||
if(overlap.hit !== null){
|
||||
if(collisionSide.y === -1){
|
||||
// Node is on top of overlap, so onGround
|
||||
node.onGround = true;
|
||||
} else if(collisionSide.y === 1){
|
||||
// Node is on bottom of overlap, so onCeiling
|
||||
node.onCeiling = true;
|
||||
} else {
|
||||
// Node wasn't touching on y, so it is touching on x
|
||||
node.onWall = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,7 +244,7 @@ export default class BasicPhysicsManager extends PhysicsManager {
|
|||
let area = node.sweptRect.overlapArea(collider);
|
||||
if(area > 0){
|
||||
// We had a collision
|
||||
overlaps.push(new AreaCollision(area, collider));
|
||||
overlaps.push(new AreaCollision(area, collider, tilemap, "Tilemap", new Vec2(col, row)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -141,6 +141,18 @@ export default class AnimationManager {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the specified animation. Does not restart it if it is already playing
|
||||
* @param animation The name of the animation to play
|
||||
* @param loop Whether or not to loop the animation. False by default
|
||||
* @param onEnd The name of an event to send when this animation naturally stops playing. This only matters if loop is false.
|
||||
*/
|
||||
playIfNotAlready(animation: string, loop: boolean = false, onEnd?: string): void {
|
||||
if(this.currentAnimation !== animation){
|
||||
this.play(animation, loop, onEnd);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Plays the specified animation
|
||||
* @param animation The name of the animation to play
|
||||
|
|
|
@ -77,20 +77,23 @@ export default class TilemapFactory {
|
|||
|
||||
let sceneLayer;
|
||||
let isParallaxLayer = false;
|
||||
let depth = 0;
|
||||
|
||||
if(layer.properties){
|
||||
for(let prop of layer.properties){
|
||||
if(prop.name === "Parallax"){
|
||||
isParallaxLayer = prop.value;
|
||||
} else if(prop.name === "Depth") {
|
||||
depth = prop.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(isParallaxLayer){
|
||||
console.log("Adding parallax layer: " + layer.name)
|
||||
sceneLayer = this.scene.addParallaxLayer(layer.name, new Vec2(1, 1));
|
||||
sceneLayer = this.scene.addParallaxLayer(layer.name, new Vec2(1, 1), depth);
|
||||
} else {
|
||||
sceneLayer = this.scene.addLayer(layer.name);
|
||||
sceneLayer = this.scene.addLayer(layer.name, depth);
|
||||
}
|
||||
|
||||
if(layer.type === "tilelayer"){
|
||||
|
@ -144,19 +147,19 @@ export default class TilemapFactory {
|
|||
// Layer is an object layer, so add each object as a sprite to a new layer
|
||||
for(let obj of layer.objects){
|
||||
// Check if obj is collidable
|
||||
let isCollidable = false;
|
||||
let hasPhysics = false;
|
||||
let isStatic = true;
|
||||
let isCollidable = false;
|
||||
let isTrigger = false;
|
||||
let group = "";
|
||||
|
||||
if(obj.properties){
|
||||
for(let prop of obj.properties){
|
||||
if(prop.name === "Collidable"){
|
||||
isCollidable = prop.value;
|
||||
} else if(prop.name === "Static"){
|
||||
isStatic = prop.value;
|
||||
} else if(prop.name === "hasPhysics"){
|
||||
if(prop.name === "HasPhysics"){
|
||||
hasPhysics = prop.value;
|
||||
} else if(prop.name === "Collidable"){
|
||||
isCollidable = prop.value;
|
||||
} else if(prop.name === "IsTrigger"){
|
||||
isTrigger = prop.value;
|
||||
} else if(prop.name === "Group"){
|
||||
group = prop.value;
|
||||
}
|
||||
|
@ -194,8 +197,10 @@ export default class TilemapFactory {
|
|||
|
||||
// Now we have sprite. Associate it with our physics object if there is one
|
||||
if(hasPhysics){
|
||||
sprite.addPhysics(sprite.boundary.clone(), Vec2.ZERO, isCollidable, isStatic);
|
||||
// Make the sprite a static physics object
|
||||
sprite.addPhysics(sprite.boundary.clone(), Vec2.ZERO, isCollidable, true);
|
||||
sprite.group = group;
|
||||
sprite.isTrigger = isTrigger;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -180,7 +180,7 @@ export default class Scene implements Updateable {
|
|||
this.renderingManager.render(visibleSet, this.tilemaps, this.uiLayers);
|
||||
|
||||
let nodes = this.sceneGraph.getAllNodes();
|
||||
this.tilemaps.forEach(tilemap => tilemap.visible && tilemap.debugRender());
|
||||
this.tilemaps.forEach(tilemap => tilemap.visible ? nodes.push(tilemap) : 0);
|
||||
Debug.setNodes(nodes);
|
||||
}
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ export default class Viewport {
|
|||
/** The size of the canvas */
|
||||
private canvasSize: Vec2;
|
||||
|
||||
constructor(initialPosition: Vec2, canvasSize: Vec2){
|
||||
constructor(canvasSize: Vec2, zoomLevel: number){
|
||||
this.view = new AABB(Vec2.ZERO, Vec2.ZERO);
|
||||
this.boundary = new AABB(Vec2.ZERO, Vec2.ZERO);
|
||||
this.lastPositions = new Queue();
|
||||
|
@ -46,13 +46,20 @@ export default class Viewport {
|
|||
this.canvasSize = Vec2.ZERO;
|
||||
this.focus = Vec2.ZERO;
|
||||
|
||||
// Set the center (and make the viewport stay there)
|
||||
this.setCenter(initialPosition);
|
||||
this.setFocus(initialPosition);
|
||||
// Set the size of the canvas
|
||||
this.setCanvasSize(canvasSize);
|
||||
|
||||
console.log(canvasSize, zoomLevel);
|
||||
|
||||
// Set the size of the viewport
|
||||
this.setSize(canvasSize);
|
||||
this.setCanvasSize(canvasSize);
|
||||
this.setZoomLevel(zoomLevel);
|
||||
|
||||
console.log(this.getHalfSize().toString());
|
||||
|
||||
// Set the center (and make the viewport stay there)
|
||||
this.setCenter(this.view.halfSize.clone());
|
||||
this.setFocus(this.view.halfSize.clone());
|
||||
}
|
||||
|
||||
/** Enables the viewport to zoom in and out */
|
||||
|
|
|
@ -11,6 +11,22 @@ export default class MathUtils {
|
|||
return x < 0 ? -1 : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not x is between a and b
|
||||
* @param a The min bound
|
||||
* @param b The max bound
|
||||
* @param x The value to check
|
||||
* @param exclusive Whether or not a and b are exclusive bounds
|
||||
* @returns True if x is between a and b, false otherwise
|
||||
*/
|
||||
static between(a: number, b: number, x: number, exclusive?: boolean): boolean {
|
||||
if(exclusive){
|
||||
return (a < x) && (x < b);
|
||||
} else {
|
||||
return (a <= x) && (x <= b);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clamps the value x to the range [min, max], rounding up or down if needed
|
||||
* @param x The value to be clamped
|
||||
|
|
2
src/Wolfie2D/_Demos/readme.md
Normal file
2
src/Wolfie2D/_Demos/readme.md
Normal file
|
@ -0,0 +1,2 @@
|
|||
# Demos
|
||||
This folder contains the demo projects created in the guides section of the Wolfie2D documentation, as well as any extra demos created for Wolfie2D.
|
|
@ -1,7 +1,6 @@
|
|||
/* #################### IMPORTS #################### */
|
||||
// Import from Wolfie2D or your own files here
|
||||
import Vec2 from "./Wolfie2D/DataTypes/Vec2";
|
||||
import Debug from "./Wolfie2D/Debug/Debug";
|
||||
import Input from "./Wolfie2D/Input/Input";
|
||||
import Graphic from "./Wolfie2D/Nodes/Graphic";
|
||||
import { GraphicType } from "./Wolfie2D/Nodes/Graphics/GraphicTypes";
|
||||
|
@ -32,7 +31,7 @@ export default class default_scene extends Scene {
|
|||
// The first argument is the key of the sprite (you get to decide what it is).
|
||||
// The second argument is the path to the actual image.
|
||||
// Paths start in the "dist/" folder, so start building your path from there
|
||||
this.load.image("logo", "assets/wolfie2d_text.png");
|
||||
this.load.image("logo", "demo_assets/wolfie2d_text.png");
|
||||
}
|
||||
|
||||
// startScene() is where you should build any game objects you wish to have in your scene,
|
||||
|
|
16
src/main.ts
16
src/main.ts
|
@ -1,13 +1,19 @@
|
|||
import Game from "./Wolfie2D/Loop/Game";
|
||||
import default_scene from "./default_scene";
|
||||
import Platformer from "./Platformer";
|
||||
|
||||
// The main function is your entrypoint into Wolfie2D. Specify your first scene and any options here.
|
||||
(function main(){
|
||||
// These are options for initializing the game
|
||||
// Here, we'll simply set the size of the viewport, and make the background of the game black
|
||||
// Here, we'll set the size of the viewport, color the background, and set up key bindings.
|
||||
let options = {
|
||||
viewportSize: {x: 800, y: 600},
|
||||
clearColor: {r: 0, g: 0, b: 0},
|
||||
canvasSize: {x: 800, y: 600},
|
||||
zoomLevel: 4,
|
||||
clearColor: {r: 34, g: 32, b: 52},
|
||||
inputs: [
|
||||
{ name: "left", keys: ["a"] },
|
||||
{ name: "right", keys: ["d"] },
|
||||
{ name: "jump", keys: ["space", "w"]}
|
||||
]
|
||||
}
|
||||
|
||||
// Create our game. This will create all of the systems.
|
||||
|
@ -20,5 +26,5 @@ import default_scene from "./default_scene";
|
|||
let sceneOptions = {};
|
||||
|
||||
// Add our first scene. This will load this scene into the game world.
|
||||
demoGame.getSceneManager().addScene(default_scene, sceneOptions);
|
||||
demoGame.getSceneManager().addScene(Platformer, sceneOptions);
|
||||
})();
|
Loading…
Reference in New Issue
Block a user