├── README.md ├── .gitignore ├── sprites ├── moves.pdn ├── hurt.png ├── pawn.png ├── queen.png ├── tip.png ├── bonus.png ├── bonus_star.png ├── button.png ├── moves.png ├── needle.png ├── next_move.png ├── pawn_alt.png ├── pillar.png ├── player.png ├── chessboard.png ├── chesstris-04.png ├── chesstris-05.png ├── chesstris-06.png ├── chesstris-07.png ├── chesstris-08.png ├── chesstris-09.png ├── speech_bubble.png ├── start_button.png ├── elevator_operator.png ├── floor_indicator.png ├── helevator_door.png ├── move_select_outline.png ├── board_select_outline.png ├── tip.png.import ├── hurt.png.import ├── pawn.png.import ├── bonus.png.import ├── moves.png.import ├── queen.png.import ├── button.png.import ├── needle.png.import ├── pillar.png.import ├── player.png.import ├── pawn_alt.png.import ├── next_move.png.import ├── bonus_star.png.import ├── chessboard.png.import ├── chesstris-04.png.import ├── chesstris-05.png.import ├── chesstris-06.png.import ├── chesstris-07.png.import ├── chesstris-08.png.import ├── chesstris-09.png.import ├── speech_bubble.png.import ├── start_button.png.import ├── helevator_door.png.import ├── floor_indicator.png.import ├── elevator_operator.png.import ├── move_select_outline.png.import └── board_select_outline.png.import ├── icon.png ├── sounds ├── combo.wav ├── combo2.wav ├── enemy_die.wav ├── hurt1.wav ├── bonus_move1.wav ├── bonus_move2.wav ├── button_press.wav ├── button_press2.wav ├── elevator_ride.wav ├── ld48_bgmusic.ogg ├── elevator_arrived.wav ├── select_move_index.wav ├── select_move_target.wav ├── select_move_target2.wav ├── ld48_bgmusic.ogg.import ├── combo.wav.import ├── hurt1.wav.import ├── combo2.wav.import ├── enemy_die.wav.import ├── bonus_move1.wav.import ├── bonus_move2.wav.import ├── button_press.wav.import ├── button_press2.wav.import ├── elevator_ride.wav.import ├── elevator_arrived.wav.import ├── select_move_index.wav.import ├── select_move_target.wav.import └── select_move_target2.wav.import ├── backgrounds ├── gameover.png ├── title.png ├── tutorial.png ├── youwin.png ├── background.png ├── title.png.import ├── youwin.png.import ├── gameover.png.import ├── tutorial.png.import └── background.png.import ├── fonts ├── ComicNeue-Bold.ttf ├── ComicNeue-Italic.ttf ├── ComicNeue-Light.ttf ├── ComicNeue-BoldItalic.ttf ├── ComicNeue-LightItalic.ttf ├── ComicNeue-Regular.ttf └── OFL.txt ├── screenshot ├── screenshot-0.png ├── screenshot-1.png ├── screenshot-0.png.import └── screenshot-1.png.import ├── scripts ├── death_count.gd ├── move_type.gd ├── button_logic.gd ├── tip.gd ├── hurt_flash.gd ├── menu_button.gd ├── piece_logic.gd ├── phases.gd ├── bonus_star.gd ├── intvec2.gd ├── bonus_flash.gd ├── move_display.gd ├── chessboard.gd ├── elevator_button.gd ├── floor_indicator.gd ├── main_scene.gd ├── board_button.gd ├── hellevator.gd ├── elevator_operator.gd ├── pawn_formation_factory.gd ├── dialogue_manager.gd ├── move_button.gd ├── pawn.gd ├── controller.gd ├── player.gd └── logic_manager.gd ├── default_env.tres ├── entities ├── controller.tscn ├── music_controller.tscn ├── tip.tscn ├── bonus_star.tscn ├── bonus_flash.tscn ├── chessboard.tscn ├── move_display.tscn ├── hurt_flash.tscn ├── death_count.tscn ├── elevator_button.tscn ├── pawn.tscn ├── floor_indicator.tscn ├── board_button.tscn ├── menu_button.tscn ├── player.tscn ├── hellevator.tscn ├── elevator_operator.tscn └── move_button.tscn ├── default_bus_layout.tres ├── levels ├── menu.tscn ├── tutorial.tscn ├── youwin.tscn ├── gameover.tscn └── main.tscn ├── icon.png.import ├── dialogue ├── project.godot └── .gitattributes /README.md: -------------------------------------------------------------------------------- 1 | # README 2 | 3 | This is a game. 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .import/ 2 | export.cfg 3 | export_presets.cfg 4 | build/ 5 | -------------------------------------------------------------------------------- /sprites/moves.pdn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boxedmeatrevolution/chesstris/HEAD/sprites/moves.pdn -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:2c160bfdb8d0423b958083202dc7b58d499cbef22f28d2a58626884378ce9b7f 3 | size 3305 4 | -------------------------------------------------------------------------------- /sprites/hurt.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4733eaa014dd1e593b524db7e48bc94144fd53984491124ff9b7019c973316b8 3 | size 2057 4 | -------------------------------------------------------------------------------- /sprites/pawn.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:a0c627d6fc2cfb76791fbb4d0d9f6af6410214f9b6269fd57fd286006caf6cd6 3 | size 19138 4 | -------------------------------------------------------------------------------- /sprites/queen.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ca8b8d38cde183942eafc80858afdc20afe5063ac5ca0637b294f6b89be66be6 3 | size 7550 4 | -------------------------------------------------------------------------------- /sprites/tip.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:682884c74bb3efb12f878ea62098077c9fe681cfab3f8ba49aaf489bfa80494a 3 | size 64406 4 | -------------------------------------------------------------------------------- /sounds/combo.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b7f2335120547679a24f6e812fd33c302be967687d998923927931551ca0fd3f 3 | size 453598 4 | -------------------------------------------------------------------------------- /sounds/combo2.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:62d45cf18842a7767c5cb7723aa19212586af6d2a8e07eed5034775b72b8d7df 3 | size 453598 4 | -------------------------------------------------------------------------------- /sounds/enemy_die.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:88bd41368a72048e38b5a99602994b82eb30343025ed5c8278f302e06360a8e5 3 | size 907102 4 | -------------------------------------------------------------------------------- /sounds/hurt1.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:964828000cb3c16ef4d9ee750f4daf7f17b5f7543a7cb05f29892f47a833d9da 3 | size 453598 4 | -------------------------------------------------------------------------------- /sprites/bonus.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:8ce4a5252b4c4c3ad785d6c5b5bd895901d95c104bc857dc664fc6fa060c8dfa 3 | size 28509 4 | -------------------------------------------------------------------------------- /sprites/bonus_star.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7b92dc7bbb61d6ede26da0312ecc6d0657700343dfecd011abc4ba92cb57bbbe 3 | size 1101 4 | -------------------------------------------------------------------------------- /sprites/button.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7fa56dcfd8be3212cdbb6c400f9938023894855561aad9a983d4b82453762bf7 3 | size 22338 4 | -------------------------------------------------------------------------------- /sprites/moves.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e86eb6d7fad901d8ace9dbd0a726c8b15f9d11f22e3b400b7e3491aec01a5b2b 3 | size 19892 4 | -------------------------------------------------------------------------------- /sprites/needle.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3c94a1de430f7fa1bc7fa96d75e7d2ac882cc59af3c69411cfbb55a0f1a3c376 3 | size 2454 4 | -------------------------------------------------------------------------------- /sprites/next_move.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:bbf48397d55ab3da28f0b89be58024944e2750100b2c58ebec3354a0f86431da 3 | size 24084 4 | -------------------------------------------------------------------------------- /sprites/pawn_alt.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:715b00e3655f839c5b1bf811dbff67b16848967a0680c5527a9bf7b9d8c5699b 3 | size 7041 4 | -------------------------------------------------------------------------------- /sprites/pillar.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:df0bf4b9cd247196c76cc320fc94029624b78ffb067672f4a215f6cde888cdca 3 | size 25746 4 | -------------------------------------------------------------------------------- /sprites/player.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d5ac4eba73618f97568b8e0d2b432391f6fbc6c71e90785f09cee5da25a287fb 3 | size 5124 4 | -------------------------------------------------------------------------------- /backgrounds/gameover.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ee0846f6cddaf1587fae66f528673678c71ec864e16160ebcc51cd305e9d0368 3 | size 326173 4 | -------------------------------------------------------------------------------- /backgrounds/title.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d199abf6f2943eb2fc52c825db6dd0d5652673c586275b2a8c566eb889df9fdf 3 | size 402121 4 | -------------------------------------------------------------------------------- /backgrounds/tutorial.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:3481cb836ac59a51bd945f500d8d43d12dbc33006566a2fdabb4c76ff7eefc14 3 | size 370039 4 | -------------------------------------------------------------------------------- /backgrounds/youwin.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cc6d8a2ec6855fc8158ad0e0eecbcf378a3b031bc245d441ca1fcb829b1d30dd 3 | size 276598 4 | -------------------------------------------------------------------------------- /fonts/ComicNeue-Bold.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ac728ebfb24a9bcb1dc71f030a0743fd6a2b71df90dfcb9877a03b32ffb44069 3 | size 53344 4 | -------------------------------------------------------------------------------- /fonts/ComicNeue-Italic.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4e32ccd8762275b3b418d927887eccabac125d6f5535ff0979ff3e81d36a3c5d 3 | size 51764 4 | -------------------------------------------------------------------------------- /fonts/ComicNeue-Light.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ce0caeaf0d72d23d7052533243241e6edc316db7b517f658aec35b604cdafd12 3 | size 53352 4 | -------------------------------------------------------------------------------- /sounds/bonus_move1.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:587da2a8fd071bcdcb5efb7c6c64581e3bbdad4a8726e1f7543d8e2d95f9481b 3 | size 453598 4 | -------------------------------------------------------------------------------- /sounds/bonus_move2.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:89e0f79b819472200fa48e0ae1d3aa300e36be0914a91ebea0872f97b4597334 3 | size 453598 4 | -------------------------------------------------------------------------------- /sounds/button_press.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4d4e37aae87e6c4346ff1fde99b363443cef3a1678285122bf3d8de090e3d56b 3 | size 907102 4 | -------------------------------------------------------------------------------- /sounds/button_press2.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f2739bd00f7c02631e871b1f7eeddf98134ba576fdce991e6f363c37c1e1261f 3 | size 907102 4 | -------------------------------------------------------------------------------- /sounds/elevator_ride.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:c9e8feb91c36c0e357227a53f36bb51e6486375e6f93783faf911e72b5b66526 3 | size 907102 4 | -------------------------------------------------------------------------------- /sounds/ld48_bgmusic.ogg: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ca1d0a4ad634f8559676956a7db393192db11b7f14ab75e861c4801e0e2d4036 3 | size 1482098 4 | -------------------------------------------------------------------------------- /sprites/chessboard.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:4f0c3129c9b70de77288bd6f1294ee53c4c6895dac5c3699583615d81a873c3a 3 | size 294341 4 | -------------------------------------------------------------------------------- /sprites/chesstris-04.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e4c3ceb8d520db6aa6e54d9dd78eddab2cc6c9ed653ae8e49593747246681407 3 | size 2251 4 | -------------------------------------------------------------------------------- /sprites/chesstris-05.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d7ab42ecb3d7e7eea9120f6e2c3006d25a433168501562a900bb924038f0b256 3 | size 3467 4 | -------------------------------------------------------------------------------- /sprites/chesstris-06.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:de154e7f28573ccbce67abf9e0ed3c1c1cd847e2491de1ebea96e560eb5f52d4 3 | size 3645 4 | -------------------------------------------------------------------------------- /sprites/chesstris-07.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0b7f5e601fcbcb3b9a66a79c934ecdeeb0a62b072e3b32ef0097ee099d615dbc 3 | size 3822 4 | -------------------------------------------------------------------------------- /sprites/chesstris-08.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:0adef22e57a1e8770ef7483e619642bff02ff2908bb1788307b7638cdd091426 3 | size 3049 4 | -------------------------------------------------------------------------------- /sprites/chesstris-09.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:ffc614e2cd4fb077a0ca28a77d066e5557be223112efb6214aaf6fed19756fc2 3 | size 2060 4 | -------------------------------------------------------------------------------- /sprites/speech_bubble.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:70d8b5e8ffe924bfa089efced4be3f31d170aa654a09eea414be5cea525956cb 3 | size 16893 4 | -------------------------------------------------------------------------------- /sprites/start_button.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7262a665ec6fed260e90e70190232fe15f3e50d301e6f06ce26b3ee676d5f246 3 | size 25070 4 | -------------------------------------------------------------------------------- /backgrounds/background.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:dd47202c151bd6b0fcba5f5972632ec546a92cd51d437eb6e4096835488ec72d 3 | size 472816 4 | -------------------------------------------------------------------------------- /fonts/ComicNeue-BoldItalic.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9b71d59d6ff8ab8117e1ca1acdc6b11e820bde27c6943a0db4f24edb3b63028a 3 | size 53248 4 | -------------------------------------------------------------------------------- /fonts/ComicNeue-LightItalic.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d757dee97623fcd9fa151d0a5ff60f883935f5a517c13e00724cdc4e7f1c6fe4 3 | size 51544 4 | -------------------------------------------------------------------------------- /fonts/ComicNeue-Regular.ttf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:e4f99242195800cc7471d1e7ac47960d1eb1cec8f0f147598a51f01b428f7d3c 3 | size 54808 4 | -------------------------------------------------------------------------------- /screenshot/screenshot-0.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:381b50cd14bcd46a4994483e9672b218f5d1bd0c2e41bb305fa356a1a457c99b 3 | size 439420 4 | -------------------------------------------------------------------------------- /screenshot/screenshot-1.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:426090367c165d9ba9c840820a6444cc17fb595c5f1b55e8c70bf250af58931a 3 | size 598493 4 | -------------------------------------------------------------------------------- /sounds/elevator_arrived.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:27bf017fc6d43e4001c654b0156386193669be6e7dd43b0b7b1d847f88eaec40 3 | size 907102 4 | -------------------------------------------------------------------------------- /sounds/select_move_index.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:cfc7b4a54a622d5aad5bf12c0371b2325de81d0417cbd18476c93cc32808187d 3 | size 50632 4 | -------------------------------------------------------------------------------- /sounds/select_move_target.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:76e0d7bce7d18bcb5ee3aa042e721666a323e786c686c34a491a8a5277e3a6a2 3 | size 129796 4 | -------------------------------------------------------------------------------- /sounds/select_move_target2.wav: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:aba7813934c7037ff506d97f73571d74a1753a4d1c68325de9a570c6a4223c5e 3 | size 453598 4 | -------------------------------------------------------------------------------- /sprites/elevator_operator.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:9bd8bd2687acd995ef4c14110e95c4a2435f9a40e2445f8b383de7b6c3814ffa 3 | size 178314 4 | -------------------------------------------------------------------------------- /sprites/floor_indicator.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:82cd596e8cb1b43a25fe6509293fdb3005a46700fef1ccf46c4ecc081b052f80 3 | size 13083 4 | -------------------------------------------------------------------------------- /sprites/helevator_door.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:58e0e3bb2d92dd6fa33009c4c064aae5e6e93fb0f441b8cb58c9c2735a8b1cb3 3 | size 172781 4 | -------------------------------------------------------------------------------- /sprites/move_select_outline.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:17379114c2b91f856b450d1002f1de4080a3f841282d5e0bfdf5617605187980 3 | size 20897 4 | -------------------------------------------------------------------------------- /sprites/board_select_outline.png: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:f868d20ec3f8cad95dbd885bcf0d4763ba45da16891cd1186fc27d4a5e4eb5a4 3 | size 36239 4 | -------------------------------------------------------------------------------- /scripts/death_count.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | onready var label := $Label 4 | 5 | func _ready() -> void: 6 | self.label.text = "Death count: %s" % (LogicManager.death_count) 7 | -------------------------------------------------------------------------------- /default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | 5 | [resource] 6 | background_mode = 2 7 | background_sky = SubResource( 1 ) 8 | -------------------------------------------------------------------------------- /scripts/move_type.gd: -------------------------------------------------------------------------------- 1 | extends Reference 2 | class_name MoveType 3 | 4 | const NULL = 0 5 | const BAD_PAWN = 1 6 | const KNIGHT = 2 7 | const BISHOP = 3 8 | const ROOK = 4 9 | const QUEEN = 5 10 | const KING = 6 11 | const GOOD_PAWN = 7 12 | -------------------------------------------------------------------------------- /entities/controller.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://scripts/controller.gd" type="Script" id=1] 4 | 5 | [node name="Controller" type="Node2D"] 6 | script = ExtResource( 1 ) 7 | __meta__ = { 8 | "_edit_group_": true 9 | } 10 | -------------------------------------------------------------------------------- /entities/music_controller.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=2 format=2] 2 | 3 | [ext_resource path="res://sounds/ld48_bgmusic.ogg" type="AudioStream" id=1] 4 | 5 | [node name="MusicController" type="Node2D"] 6 | 7 | [node name="AudioStreamPlayer" type="AudioStreamPlayer" parent="."] 8 | stream = ExtResource( 1 ) 9 | autoplay = true 10 | bus = "Music" 11 | -------------------------------------------------------------------------------- /entities/tip.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://sprites/tip.png" type="Texture" id=1] 4 | [ext_resource path="res://scripts/tip.gd" type="Script" id=6] 5 | 6 | [node name="Tip" type="Node2D"] 7 | script = ExtResource( 6 ) 8 | 9 | [node name="Background" type="Sprite" parent="."] 10 | texture = ExtResource( 1 ) 11 | -------------------------------------------------------------------------------- /scripts/button_logic.gd: -------------------------------------------------------------------------------- 1 | extends Object 2 | 3 | class_name ButtonLogic 4 | 5 | 6 | var id : int = -1 7 | var pos : IntVec2 8 | var pressed : bool = false 9 | 10 | 11 | func _init(params) -> void: 12 | self.id = params['id'] 13 | self.pos = params['pos'] 14 | 15 | func _to_string() -> String: 16 | return "Id: %s, Pos: %s, Pressed: %s" % [id, pos, pressed] 17 | -------------------------------------------------------------------------------- /entities/bonus_star.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://scripts/bonus_star.gd" type="Script" id=1] 4 | [ext_resource path="res://sprites/bonus_star.png" type="Texture" id=2] 5 | 6 | [node name="BonusStar" type="Node2D"] 7 | script = ExtResource( 1 ) 8 | 9 | [node name="Sprite" type="Sprite" parent="."] 10 | texture = ExtResource( 2 ) 11 | -------------------------------------------------------------------------------- /scripts/tip.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | func _ready(): 4 | if LogicManager.level <= 1 || DialogueManager.seen_tip: 5 | queue_free() 6 | else: 7 | DialogueManager.seen_tip = true 8 | 9 | func _input(event : InputEvent) -> void: 10 | get_tree().set_input_as_handled() 11 | if event is InputEventMouseButton && event.pressed && event.button_index == BUTTON_LEFT: 12 | queue_free() 13 | -------------------------------------------------------------------------------- /default_bus_layout.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="AudioBusLayout" format=2] 2 | 3 | [resource] 4 | bus/1/name = "SoundEffects" 5 | bus/1/solo = false 6 | bus/1/mute = false 7 | bus/1/bypass_fx = false 8 | bus/1/volume_db = 0.0 9 | bus/1/send = "Master" 10 | bus/2/name = "Music" 11 | bus/2/solo = false 12 | bus/2/mute = false 13 | bus/2/bypass_fx = false 14 | bus/2/volume_db = -9.42178 15 | bus/2/send = "Master" 16 | -------------------------------------------------------------------------------- /sounds/ld48_bgmusic.ogg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="ogg_vorbis" 4 | type="AudioStreamOGGVorbis" 5 | path="res://.import/ld48_bgmusic.ogg-06231e437b405a32f0795a2fa241438d.oggstr" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/ld48_bgmusic.ogg" 10 | dest_files=[ "res://.import/ld48_bgmusic.ogg-06231e437b405a32f0795a2fa241438d.oggstr" ] 11 | 12 | [params] 13 | 14 | loop=true 15 | loop_offset=0 16 | -------------------------------------------------------------------------------- /entities/bonus_flash.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://sprites/bonus.png" type="Texture" id=1] 4 | [ext_resource path="res://scripts/bonus_flash.gd" type="Script" id=2] 5 | 6 | [node name="HurtFlash" type="Node2D"] 7 | script = ExtResource( 2 ) 8 | __meta__ = { 9 | "_edit_group_": true 10 | } 11 | 12 | [node name="Sprite" type="Sprite" parent="."] 13 | texture = ExtResource( 1 ) 14 | -------------------------------------------------------------------------------- /scripts/hurt_flash.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const LIFE = 0.25 4 | var timer := 0.0 5 | onready var sprite := $Sprite 6 | 7 | func _ready() -> void: 8 | self.sprite.rotation_degrees = randf() * 360 9 | 10 | func _process(delta : float) -> void: 11 | self.sprite.rotation_degrees += 180 * delta 12 | timer += delta 13 | if timer > LIFE: 14 | queue_free() 15 | else: 16 | self.sprite.modulate.a = 1.0 - timer / LIFE 17 | -------------------------------------------------------------------------------- /entities/chessboard.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://sprites/chessboard.png" type="Texture" id=1] 4 | [ext_resource path="res://scripts/chessboard.gd" type="Script" id=2] 5 | 6 | [node name="ChessBoard" type="Node2D"] 7 | script = ExtResource( 2 ) 8 | 9 | [node name="Sprite" type="Sprite" parent="."] 10 | position = Vector2( 0, 96 ) 11 | texture = ExtResource( 1 ) 12 | centered = false 13 | -------------------------------------------------------------------------------- /entities/move_display.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://scripts/move_display.gd" type="Script" id=1] 4 | [ext_resource path="res://sprites/moves.png" type="Texture" id=2] 5 | 6 | [node name="MoveDisplay" type="Node2D"] 7 | script = ExtResource( 1 ) 8 | __meta__ = { 9 | "_edit_group_": true 10 | } 11 | 12 | [node name="Sprite" type="Sprite" parent="."] 13 | texture = ExtResource( 2 ) 14 | hframes = 7 15 | -------------------------------------------------------------------------------- /scripts/menu_button.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | onready var sprite := $Sprite 4 | export var scene_to := "" 5 | 6 | func _area_input(v : Node2D, e : InputEvent, idx : int) -> void: 7 | if e is InputEventMouseButton && e.pressed && e.button_index == BUTTON_LEFT: 8 | get_tree().change_scene(self.scene_to) 9 | 10 | func _mouse_enter() -> void: 11 | self.sprite.frame = 0 12 | 13 | func _mouse_leave() -> void: 14 | self.sprite.frame = 1 15 | -------------------------------------------------------------------------------- /entities/hurt_flash.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://sprites/hurt.png" type="Texture" id=1] 4 | [ext_resource path="res://scripts/hurt_flash.gd" type="Script" id=2] 5 | 6 | [node name="HurtFlash" type="Node2D"] 7 | script = ExtResource( 2 ) 8 | __meta__ = { 9 | "_edit_group_": true 10 | } 11 | 12 | [node name="Sprite" type="Sprite" parent="."] 13 | scale = Vector2( 2, 2 ) 14 | texture = ExtResource( 1 ) 15 | -------------------------------------------------------------------------------- /levels/menu.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://backgrounds/title.png" type="Texture" id=1] 4 | [ext_resource path="res://entities/menu_button.tscn" type="PackedScene" id=2] 5 | 6 | [node name="Menu" type="Node2D"] 7 | 8 | [node name="Sprite" type="Sprite" parent="."] 9 | texture = ExtResource( 1 ) 10 | centered = false 11 | 12 | [node name="MenuButton" parent="." instance=ExtResource( 2 )] 13 | position = Vector2( 769, 296 ) 14 | scene_to = "res://levels/tutorial.tscn" 15 | -------------------------------------------------------------------------------- /levels/tutorial.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://backgrounds/tutorial.png" type="Texture" id=1] 4 | [ext_resource path="res://entities/menu_button.tscn" type="PackedScene" id=2] 5 | 6 | [node name="Tutorial" type="Node2D"] 7 | 8 | [node name="Sprite" type="Sprite" parent="."] 9 | texture = ExtResource( 1 ) 10 | centered = false 11 | 12 | [node name="MenuButton" parent="." instance=ExtResource( 2 )] 13 | position = Vector2( 777, 471 ) 14 | scene_to = "res://levels/main.tscn" 15 | -------------------------------------------------------------------------------- /sounds/combo.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/combo.wav-00a728bb31b2bf9e95f603c8ebd93eca.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/combo.wav" 10 | dest_files=[ "res://.import/combo.wav-00a728bb31b2bf9e95f603c8ebd93eca.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/hurt1.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/hurt1.wav-cc718162641ce8cbc7c27b3a36957faf.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/hurt1.wav" 10 | dest_files=[ "res://.import/hurt1.wav-cc718162641ce8cbc7c27b3a36957faf.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /scripts/piece_logic.gd: -------------------------------------------------------------------------------- 1 | extends Object 2 | 3 | class_name PieceLogic 4 | 5 | 6 | var id : int = -1 7 | var pos : IntVec2 8 | var type = MoveType.GOOD_PAWN 9 | var is_player : bool = false 10 | var is_dead : bool = false 11 | 12 | 13 | func _init(params) -> void: 14 | self.id = params['id'] 15 | self.pos = params['pos'] 16 | self.type = params['type'] 17 | self.is_player = params['is_player'] 18 | 19 | func _to_string() -> String: 20 | return "Id: %s, Pos: %s, Type: %s, IsPlayer %s" % [id, pos, type, is_player] 21 | -------------------------------------------------------------------------------- /sounds/combo2.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/combo2.wav-1b3a1d22d2dbb8119fe5e81591b05846.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/combo2.wav" 10 | dest_files=[ "res://.import/combo2.wav-1b3a1d22d2dbb8119fe5e81591b05846.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/enemy_die.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/enemy_die.wav-5425a580a50b7b83b099375bf3c049be.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/enemy_die.wav" 10 | dest_files=[ "res://.import/enemy_die.wav-5425a580a50b7b83b099375bf3c049be.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /scripts/phases.gd: -------------------------------------------------------------------------------- 1 | extends Reference 2 | class_name Phases 3 | 4 | const PLAYER_MOVE = 0 5 | const QUEEN_MOVE = 1 6 | const PAWN_MOVE = 2 7 | const SPAWN_ENEMY = 3 8 | const PRE_GAME = 4 9 | const GAME_OVER = 5 10 | const YOU_WIN = 6 11 | 12 | static func string(phase : int) -> String: 13 | var phases = [ 14 | "PLAYER_MOVE", "QUEEN_MOVE", "PAWN_MOVE", "SPAWN_ENEMY", 15 | "PRE_GAME", "GAME_OVER", "YOU_WIN" 16 | ] 17 | if phase < 0 || phase >= phases.size(): 18 | return "Invalid phase value %s" % phase 19 | return phases[phase] 20 | 21 | -------------------------------------------------------------------------------- /sounds/bonus_move1.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/bonus_move1.wav-f7abdc40a7fc1ae72ae652da417e48fc.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/bonus_move1.wav" 10 | dest_files=[ "res://.import/bonus_move1.wav-f7abdc40a7fc1ae72ae652da417e48fc.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/bonus_move2.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/bonus_move2.wav-a45e7797aed013b1f1258d3f92666183.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/bonus_move2.wav" 10 | dest_files=[ "res://.import/bonus_move2.wav-a45e7797aed013b1f1258d3f92666183.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/button_press.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/button_press.wav-d203973272cd51c13d011d72e6a3ca3d.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/button_press.wav" 10 | dest_files=[ "res://.import/button_press.wav-d203973272cd51c13d011d72e6a3ca3d.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/button_press2.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/button_press2.wav-c41a16c7247cc53298bb44fa6be8148d.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/button_press2.wav" 10 | dest_files=[ "res://.import/button_press2.wav-c41a16c7247cc53298bb44fa6be8148d.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/elevator_ride.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/elevator_ride.wav-b0d3a0bc2ccb015338f18fc429a27f2b.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/elevator_ride.wav" 10 | dest_files=[ "res://.import/elevator_ride.wav-b0d3a0bc2ccb015338f18fc429a27f2b.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/elevator_arrived.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/elevator_arrived.wav-5eb5f49c9772ef18b942ba47a77d1884.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/elevator_arrived.wav" 10 | dest_files=[ "res://.import/elevator_arrived.wav-5eb5f49c9772ef18b942ba47a77d1884.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /scripts/bonus_star.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | var velocity := Vector2.ZERO 4 | var life := 0.0 5 | const LIFETIME := 1.0 6 | 7 | func _ready() -> void: 8 | self.rotation_degrees = randf() * 360 9 | self.velocity = 500 * Vector2(randf() - 0.5, randf() - 0.5) 10 | 11 | func _process(delta : float) -> void: 12 | self.position += self.velocity * delta 13 | self.velocity *= exp(-delta / (0.5 * LIFETIME)) 14 | self.modulate.a *= exp(-delta / (0.5 * LIFETIME)) 15 | self.rotation_degrees += 100 * delta 16 | life += delta 17 | if life > LIFETIME: 18 | queue_free() 19 | -------------------------------------------------------------------------------- /sounds/select_move_index.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/select_move_index.wav-09f21f69de29a4667cd003d1bdf04c42.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/select_move_index.wav" 10 | dest_files=[ "res://.import/select_move_index.wav-09f21f69de29a4667cd003d1bdf04c42.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/select_move_target.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/select_move_target.wav-1ab9d016c045d70be392c1d15cd1cca3.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/select_move_target.wav" 10 | dest_files=[ "res://.import/select_move_target.wav-1ab9d016c045d70be392c1d15cd1cca3.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /sounds/select_move_target2.wav.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wav" 4 | type="AudioStreamSample" 5 | path="res://.import/select_move_target2.wav-b91b159f101502ae5e2a1092b3caf66b.sample" 6 | 7 | [deps] 8 | 9 | source_file="res://sounds/select_move_target2.wav" 10 | dest_files=[ "res://.import/select_move_target2.wav-b91b159f101502ae5e2a1092b3caf66b.sample" ] 11 | 12 | [params] 13 | 14 | force/8_bit=false 15 | force/mono=false 16 | force/max_rate=false 17 | force/max_rate_hz=44100 18 | edit/trim=false 19 | edit/normalize=false 20 | edit/loop=false 21 | compress/mode=0 22 | -------------------------------------------------------------------------------- /entities/death_count.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://scripts/death_count.gd" type="Script" id=1] 4 | 5 | [sub_resource type="DynamicFontData" id=1] 6 | font_path = "res://fonts/ComicNeue-Regular.ttf" 7 | 8 | [sub_resource type="DynamicFont" id=2] 9 | size = 40 10 | font_data = SubResource( 1 ) 11 | 12 | [node name="DeathCount" type="Node2D"] 13 | script = ExtResource( 1 ) 14 | 15 | [node name="Label" type="Label" parent="."] 16 | margin_right = 40.0 17 | margin_bottom = 14.0 18 | custom_fonts/font = SubResource( 2 ) 19 | text = "Death count: 0" 20 | __meta__ = { 21 | "_edit_use_anchors_": false 22 | } 23 | -------------------------------------------------------------------------------- /entities/elevator_button.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://sprites/button.png" type="Texture" id=1] 4 | [ext_resource path="res://scripts/elevator_button.gd" type="Script" id=2] 5 | [ext_resource path="res://sounds/button_press.wav" type="AudioStream" id=3] 6 | 7 | [node name="ElevatorButton" type="Node2D"] 8 | script = ExtResource( 2 ) 9 | 10 | [node name="Sprite" type="Sprite" parent="."] 11 | texture = ExtResource( 1 ) 12 | hframes = 2 13 | 14 | [node name="PressStream" type="AudioStreamPlayer2D" parent="."] 15 | stream = ExtResource( 3 ) 16 | volume_db = 4.039 17 | attenuation = 1.18921 18 | bus = "SoundEffects" 19 | -------------------------------------------------------------------------------- /entities/pawn.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://sounds/enemy_die.wav" type="AudioStream" id=1] 4 | [ext_resource path="res://scripts/pawn.gd" type="Script" id=2] 5 | 6 | [sub_resource type="StreamTexture" id=1] 7 | flags = 4 8 | load_path = "res://.import/pawn_alt.png-eb189eb5d88f87009ef2d5075972e326.stex" 9 | 10 | [node name="Pawn" type="Node2D"] 11 | script = ExtResource( 2 ) 12 | __meta__ = { 13 | "_edit_group_": true 14 | } 15 | 16 | [node name="Sprite" type="Sprite" parent="."] 17 | texture = SubResource( 1 ) 18 | 19 | [node name="EnemyDeathStream" type="AudioStreamPlayer2D" parent="."] 20 | stream = ExtResource( 1 ) 21 | -------------------------------------------------------------------------------- /scripts/intvec2.gd: -------------------------------------------------------------------------------- 1 | extends Object 2 | 3 | class_name IntVec2 4 | 5 | var x : int = 0 6 | var y : int = 0 7 | 8 | func _init(x_ : int, y_ : int) -> void: 9 | self.x = x_ 10 | self.y = y_ 11 | 12 | func _to_string(): 13 | return "(%s, %s)" % [x, y] 14 | 15 | func add(other : IntVec2) -> IntVec2: 16 | return get_script().new(other.x + self.x, other.y + self.y) 17 | 18 | func sub(other : IntVec2) -> IntVec2: 19 | return get_script().new(self.x - other.x, self.y - other.y) 20 | 21 | func scale(other : int) -> IntVec2: 22 | return get_script().new(other * self.x, other * self.y) 23 | 24 | func equals(other : IntVec2) -> bool: 25 | return self.x == other.x && self.y == other.y 26 | -------------------------------------------------------------------------------- /levels/youwin.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://backgrounds/youwin.png" type="Texture" id=1] 4 | [ext_resource path="res://entities/menu_button.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://entities/death_count.tscn" type="PackedScene" id=3] 6 | 7 | [node name="Youwin" type="Node2D"] 8 | 9 | [node name="Sprite" type="Sprite" parent="."] 10 | texture = ExtResource( 1 ) 11 | centered = false 12 | 13 | [node name="MenuButton" parent="." instance=ExtResource( 2 )] 14 | position = Vector2( 798, 480 ) 15 | scene_to = "res://levels/main.tscn" 16 | 17 | [node name="DeathCount" parent="." instance=ExtResource( 3 )] 18 | position = Vector2( 122.324, 542.981 ) 19 | -------------------------------------------------------------------------------- /scripts/bonus_flash.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const LIFE = 0.6 4 | var timer := 0.0 5 | onready var sprite := $Sprite 6 | const BonusStarScene := preload("res://entities/bonus_star.tscn") 7 | 8 | func _ready() -> void: 9 | self.sprite.rotation_degrees = 30*(randf() - 0.5) 10 | for i in range(0, 6): 11 | var bonus_star : Node2D = BonusStarScene.instance() 12 | self.get_parent().add_child(bonus_star) 13 | bonus_star.position = self.position + 40 * Vector2(randf() - 0.5, randf() - 0.5) 14 | 15 | func _process(delta : float) -> void: 16 | self.sprite.rotation_degrees -= 10 * delta 17 | timer += delta 18 | if timer > LIFE: 19 | queue_free() 20 | else: 21 | self.sprite.modulate.a = 1.0 - tanh(timer / LIFE) 22 | -------------------------------------------------------------------------------- /entities/floor_indicator.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://sprites/floor_indicator.png" type="Texture" id=1] 4 | [ext_resource path="res://sprites/needle.png" type="Texture" id=2] 5 | [ext_resource path="res://scripts/floor_indicator.gd" type="Script" id=3] 6 | 7 | [node name="FloorIndicator" type="Node2D"] 8 | script = ExtResource( 3 ) 9 | __meta__ = { 10 | "_edit_group_": true 11 | } 12 | 13 | [node name="Sprite" type="Sprite" parent="."] 14 | position = Vector2( -1, 0 ) 15 | texture = ExtResource( 1 ) 16 | offset = Vector2( 0, -35 ) 17 | 18 | [node name="NeedleSprite" type="Sprite" parent="."] 19 | position = Vector2( -1, 0 ) 20 | rotation = 0.10472 21 | texture = ExtResource( 2 ) 22 | offset = Vector2( 39, 0 ) 23 | -------------------------------------------------------------------------------- /levels/gameover.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://entities/tip.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://entities/menu_button.tscn" type="PackedScene" id=2] 5 | 6 | [sub_resource type="StreamTexture" id=1] 7 | resource_local_to_scene = true 8 | flags = 4 9 | load_path = "res://.import/gameover.png-6c8a820f39f7d9a7341954d0686a34d4.stex" 10 | 11 | [node name="Gameover" type="Node2D"] 12 | 13 | [node name="Sprite" type="Sprite" parent="."] 14 | texture = SubResource( 1 ) 15 | centered = false 16 | 17 | [node name="MenuButton" parent="." instance=ExtResource( 2 )] 18 | position = Vector2( 354, 514 ) 19 | scene_to = "res://levels/main.tscn" 20 | 21 | [node name="Tip" parent="." instance=ExtResource( 1 )] 22 | position = Vector2( 480, 300 ) 23 | -------------------------------------------------------------------------------- /icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/tip.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tip.png-754d9734bf7183c0532b73f07fb629ae.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/tip.png" 13 | dest_files=[ "res://.import/tip.png-754d9734bf7183c0532b73f07fb629ae.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/hurt.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/hurt.png-373d8997ea48374c890f72186ca065ae.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/hurt.png" 13 | dest_files=[ "res://.import/hurt.png-373d8997ea48374c890f72186ca065ae.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/pawn.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/pawn.png-f88158b6af78b3f4234dd4eae5a88726.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/pawn.png" 13 | dest_files=[ "res://.import/pawn.png-f88158b6af78b3f4234dd4eae5a88726.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/bonus.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/bonus.png-1ac4d41774eeda0096555ec69c74620b.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/bonus.png" 13 | dest_files=[ "res://.import/bonus.png-1ac4d41774eeda0096555ec69c74620b.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/moves.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/moves.png-bb857be74c0a4e4ac4603508c9c6ca1a.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/moves.png" 13 | dest_files=[ "res://.import/moves.png-bb857be74c0a4e4ac4603508c9c6ca1a.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/queen.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/queen.png-3a30955e4aa588798122ad9b9a3737ab.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/queen.png" 13 | dest_files=[ "res://.import/queen.png-3a30955e4aa588798122ad9b9a3737ab.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /scripts/move_display.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | onready var sprite := $Sprite 4 | 5 | func _convert_move_sprite_index(idx : int) -> int: 6 | if idx == MoveType.GOOD_PAWN: 7 | return 0 8 | elif idx == MoveType.KNIGHT: 9 | return 1 10 | elif idx == MoveType.BISHOP: 11 | return 2 12 | elif idx == MoveType.ROOK: 13 | return 3 14 | elif idx == MoveType.QUEEN: 15 | return 4 16 | elif idx == MoveType.KING: 17 | return 5 18 | else: 19 | print("Invalid move index") 20 | get_tree().quit() 21 | return 0 22 | 23 | func _ready() -> void: 24 | self.sprite.frame = _convert_move_sprite_index(LogicManager.next_move) 25 | LogicManager.connect("move_draw", self, "_move_draw") 26 | 27 | func _move_draw(move : int, slot : int, next_move : int) -> void: 28 | self.sprite.frame = _convert_move_sprite_index(next_move) 29 | -------------------------------------------------------------------------------- /sprites/button.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/button.png-13aac4604de32c9ef5dfd2bf318cd942.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/button.png" 13 | dest_files=[ "res://.import/button.png-13aac4604de32c9ef5dfd2bf318cd942.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/needle.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/needle.png-5f43d572180bec52ff3a77d0708aeb9e.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/needle.png" 13 | dest_files=[ "res://.import/needle.png-5f43d572180bec52ff3a77d0708aeb9e.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/pillar.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/pillar.png-66fd8f26bd52e3ea4536aea992732e4f.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/pillar.png" 13 | dest_files=[ "res://.import/pillar.png-66fd8f26bd52e3ea4536aea992732e4f.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/player.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/player.png-f534b8a02ffb80eefc72936296201445.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/player.png" 13 | dest_files=[ "res://.import/player.png-f534b8a02ffb80eefc72936296201445.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /backgrounds/title.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/title.png-b253768b0c7188e3b0a835296d4d5ffb.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://backgrounds/title.png" 13 | dest_files=[ "res://.import/title.png-b253768b0c7188e3b0a835296d4d5ffb.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /backgrounds/youwin.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/youwin.png-06a4e3f4654ebc332169dfab8984daab.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://backgrounds/youwin.png" 13 | dest_files=[ "res://.import/youwin.png-06a4e3f4654ebc332169dfab8984daab.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/pawn_alt.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/pawn_alt.png-eb189eb5d88f87009ef2d5075972e326.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/pawn_alt.png" 13 | dest_files=[ "res://.import/pawn_alt.png-eb189eb5d88f87009ef2d5075972e326.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/next_move.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/next_move.png-2383f08ef89cc64ad218006db2745192.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/next_move.png" 13 | dest_files=[ "res://.import/next_move.png-2383f08ef89cc64ad218006db2745192.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /backgrounds/gameover.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/gameover.png-6c8a820f39f7d9a7341954d0686a34d4.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://backgrounds/gameover.png" 13 | dest_files=[ "res://.import/gameover.png-6c8a820f39f7d9a7341954d0686a34d4.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /backgrounds/tutorial.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/tutorial.png-2b5ef7e9cdd04e6f55f4ef9714dcbdac.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://backgrounds/tutorial.png" 13 | dest_files=[ "res://.import/tutorial.png-2b5ef7e9cdd04e6f55f4ef9714dcbdac.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/bonus_star.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/bonus_star.png-71d145986d0760d48a4b690d44bcf8d1.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/bonus_star.png" 13 | dest_files=[ "res://.import/bonus_star.png-71d145986d0760d48a4b690d44bcf8d1.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/chessboard.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/chessboard.png-c11d33d5e8cbb24cd57bdb0df1b5454b.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/chessboard.png" 13 | dest_files=[ "res://.import/chessboard.png-c11d33d5e8cbb24cd57bdb0df1b5454b.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /backgrounds/background.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/background.png-d478f70cdea18b2ad5e67090ab1d398d.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://backgrounds/background.png" 13 | dest_files=[ "res://.import/background.png-d478f70cdea18b2ad5e67090ab1d398d.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/chesstris-04.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/chesstris-04.png-3105ce0964b96cf06447bdb0e6f29d15.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/chesstris-04.png" 13 | dest_files=[ "res://.import/chesstris-04.png-3105ce0964b96cf06447bdb0e6f29d15.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/chesstris-05.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/chesstris-05.png-a84e8ec7760b4b1092bd66abc44a84eb.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/chesstris-05.png" 13 | dest_files=[ "res://.import/chesstris-05.png-a84e8ec7760b4b1092bd66abc44a84eb.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/chesstris-06.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/chesstris-06.png-bfce3471c2f3c87539ec39d4b490e8ce.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/chesstris-06.png" 13 | dest_files=[ "res://.import/chesstris-06.png-bfce3471c2f3c87539ec39d4b490e8ce.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/chesstris-07.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/chesstris-07.png-82ca7feb93867a112a272569866c0845.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/chesstris-07.png" 13 | dest_files=[ "res://.import/chesstris-07.png-82ca7feb93867a112a272569866c0845.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/chesstris-08.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/chesstris-08.png-e4e02c7096dca7ed3d49ca3621cb1b3b.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/chesstris-08.png" 13 | dest_files=[ "res://.import/chesstris-08.png-e4e02c7096dca7ed3d49ca3621cb1b3b.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/chesstris-09.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/chesstris-09.png-d97787b2266004da3a2b30528f557d06.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/chesstris-09.png" 13 | dest_files=[ "res://.import/chesstris-09.png-d97787b2266004da3a2b30528f557d06.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/speech_bubble.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/speech_bubble.png-c22de7f225ac47fc46e16b26444bf330.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/speech_bubble.png" 13 | dest_files=[ "res://.import/speech_bubble.png-c22de7f225ac47fc46e16b26444bf330.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/start_button.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/start_button.png-b1e312dc7ad67d80c4c7481da918d218.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/start_button.png" 13 | dest_files=[ "res://.import/start_button.png-b1e312dc7ad67d80c4c7481da918d218.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /screenshot/screenshot-0.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/screenshot-0.png-8ae2525b2bfa36678d006f54fd65c93e.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://screenshot/screenshot-0.png" 13 | dest_files=[ "res://.import/screenshot-0.png-8ae2525b2bfa36678d006f54fd65c93e.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /screenshot/screenshot-1.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/screenshot-1.png-89462be890ac445670129601b80e7b1a.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://screenshot/screenshot-1.png" 13 | dest_files=[ "res://.import/screenshot-1.png-89462be890ac445670129601b80e7b1a.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /scripts/chessboard.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const TILE_WIDTH := 96 4 | const TILE_HEIGHT := 96 5 | const NUM_WIDTH := 6 6 | const NUM_HEIGHT := 7 7 | 8 | 9 | func get_pos(ipos : IntVec2) -> Vector2: 10 | if ipos.x < 0 || ipos.x >= NUM_WIDTH || ipos.y < 0 || ipos.y >= NUM_HEIGHT: 11 | return Vector2(NAN, NAN) 12 | var origin := position 13 | var x := (ipos.x + 0.5) * TILE_WIDTH + origin.x 14 | var y := ((NUM_HEIGHT - ipos.y - 1) + 0.5) * TILE_HEIGHT + origin.y 15 | return Vector2(x, y) 16 | 17 | func get_ipos(pos : Vector2) -> IntVec2: 18 | var origin := position 19 | var ix := int(floor((pos.x - origin.x) / TILE_WIDTH)) 20 | var iy := NUM_HEIGHT - int(floor((pos.y - origin.y) / TILE_HEIGHT)) - 1 21 | if ix < 0 || ix >= NUM_WIDTH || iy < 0 || iy >= NUM_HEIGHT: 22 | return IntVec2.new(-128, -128) 23 | else: 24 | return IntVec2.new(ix, iy) 25 | -------------------------------------------------------------------------------- /sprites/helevator_door.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/helevator_door.png-fb795aaee83a61c7e9b03f78494036e0.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/helevator_door.png" 13 | dest_files=[ "res://.import/helevator_door.png-fb795aaee83a61c7e9b03f78494036e0.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/floor_indicator.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/floor_indicator.png-691a1ea2816e5d9fbf371e760daacfeb.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/floor_indicator.png" 13 | dest_files=[ "res://.import/floor_indicator.png-691a1ea2816e5d9fbf371e760daacfeb.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/elevator_operator.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/elevator_operator.png-60d732b3b3977fb5997c4045a6cfa64e.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/elevator_operator.png" 13 | dest_files=[ "res://.import/elevator_operator.png-60d732b3b3977fb5997c4045a6cfa64e.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/move_select_outline.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/move_select_outline.png-79c448588e37078e2de1aeb4c4cbb428.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/move_select_outline.png" 13 | dest_files=[ "res://.import/move_select_outline.png-79c448588e37078e2de1aeb4c4cbb428.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /sprites/board_select_outline.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/board_select_outline.png-45253198cb9d708a226fe3b01d015c44.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://sprites/board_select_outline.png" 13 | dest_files=[ "res://.import/board_select_outline.png-45253198cb9d708a226fe3b01d015c44.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /scripts/elevator_button.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const ChessBoard := preload("res://scripts/chessboard.gd") 4 | 5 | var index : int 6 | var ipos := IntVec2.new(0, 0) 7 | onready var board : ChessBoard = get_tree().get_root().find_node("ChessBoard", true, false) 8 | onready var sprite := $Sprite 9 | onready var press_stream := $PressStream 10 | 11 | func _ready() -> void: 12 | self.position = self.board.get_pos(self.ipos) 13 | LogicManager.connect("on_button_press", self, "_on_button_press") 14 | LogicManager.connect("on_level_up", self, "_on_level_up") 15 | LogicManager.connect("reset_buttons", self, "_on_reset_buttons") 16 | 17 | func _on_button_press(idx : int) -> void: 18 | if self.index == idx: 19 | self.sprite.frame = 1 20 | self.press_stream.play() 21 | 22 | func _on_level_up(floor_idx : int) -> void: 23 | queue_free() 24 | 25 | func _on_reset_buttons() -> void: 26 | queue_free() 27 | -------------------------------------------------------------------------------- /entities/board_button.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://sprites/board_select_outline.png" type="Texture" id=1] 4 | [ext_resource path="res://scripts/board_button.gd" type="Script" id=2] 5 | 6 | [sub_resource type="RectangleShape2D" id=1] 7 | extents = Vector2( 48, 48 ) 8 | 9 | [node name="BoardButton" type="Node2D"] 10 | script = ExtResource( 2 ) 11 | __meta__ = { 12 | "_edit_group_": true 13 | } 14 | 15 | [node name="Sprite" type="Sprite" parent="."] 16 | texture = ExtResource( 1 ) 17 | hframes = 2 18 | 19 | [node name="Area2D" type="Area2D" parent="."] 20 | 21 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] 22 | shape = SubResource( 1 ) 23 | 24 | [connection signal="input_event" from="Area2D" to="." method="_on_click"] 25 | [connection signal="mouse_entered" from="Area2D" to="." method="_on_mouse_enter"] 26 | [connection signal="mouse_exited" from="Area2D" to="." method="_on_mouse_leave"] 27 | -------------------------------------------------------------------------------- /entities/menu_button.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://sprites/start_button.png" type="Texture" id=1] 4 | [ext_resource path="res://scripts/menu_button.gd" type="Script" id=2] 5 | 6 | [sub_resource type="RectangleShape2D" id=1] 7 | extents = Vector2( 90, 45 ) 8 | 9 | [node name="MenuButton" type="Node2D"] 10 | script = ExtResource( 2 ) 11 | __meta__ = { 12 | "_edit_group_": true 13 | } 14 | 15 | [node name="Sprite" type="Sprite" parent="."] 16 | texture = ExtResource( 1 ) 17 | hframes = 2 18 | frame = 1 19 | 20 | [node name="Area2D" type="Area2D" parent="."] 21 | 22 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] 23 | shape = SubResource( 1 ) 24 | 25 | [connection signal="input_event" from="Area2D" to="." method="_area_input"] 26 | [connection signal="mouse_entered" from="Area2D" to="." method="_mouse_enter"] 27 | [connection signal="mouse_exited" from="Area2D" to="." method="_mouse_leave"] 28 | -------------------------------------------------------------------------------- /entities/player.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=2] 2 | 3 | [ext_resource path="res://scripts/player.gd" type="Script" id=1] 4 | [ext_resource path="res://sprites/player.png" type="Texture" id=2] 5 | [ext_resource path="res://sounds/select_move_target2.wav" type="AudioStream" id=3] 6 | [ext_resource path="res://sounds/combo.wav" type="AudioStream" id=4] 7 | [ext_resource path="res://sounds/hurt1.wav" type="AudioStream" id=5] 8 | 9 | [node name="Player" type="Node2D"] 10 | script = ExtResource( 1 ) 11 | __meta__ = { 12 | "_edit_group_": true 13 | } 14 | 15 | [node name="Sprite" type="Sprite" parent="."] 16 | texture = ExtResource( 2 ) 17 | 18 | [node name="MoveTargetClickStream" type="AudioStreamPlayer2D" parent="."] 19 | stream = ExtResource( 3 ) 20 | volume_db = 4.029 21 | bus = "SoundEffects" 22 | 23 | [node name="ComboStream" type="AudioStreamPlayer2D" parent="."] 24 | stream = ExtResource( 4 ) 25 | bus = "SoundEffects" 26 | 27 | [node name="HurtStream" type="AudioStreamPlayer2D" parent="."] 28 | stream = ExtResource( 5 ) 29 | bus = "SoundEffects" 30 | -------------------------------------------------------------------------------- /scripts/floor_indicator.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | onready var needle_sprite := $NeedleSprite 4 | 5 | const ANGLES := [174, 220, 269, -44, 6] 6 | var broken := false 7 | var state := 0 8 | var velocity := 0.0 9 | var timer := 0.0 10 | 11 | func _ready() -> void: 12 | self.set_floor(LogicManager.level) 13 | LogicManager.connect("on_level_up", self, "_on_level_up") 14 | 15 | func _process(delta : float) -> void: 16 | if self.broken: 17 | if state == 0: 18 | timer += delta 19 | self.needle_sprite.rotation_degrees = ANGLES[4] + 10 * timer * (randf() - 0.5) 20 | if timer > 2.5: 21 | state = 1 22 | velocity = 140 23 | elif state == 1: 24 | velocity += 100 * delta * randf() 25 | velocity = clamp(velocity, 80, 250) 26 | self.needle_sprite.rotation_degrees += velocity * delta 27 | 28 | func set_floor(floor_idx : int) -> void: 29 | if floor_idx == 5: 30 | self.broken = true 31 | else: 32 | floor_idx = min(floor_idx, ANGLES.size() - 1) 33 | self.needle_sprite.rotation_degrees = ANGLES[floor_idx] 34 | 35 | func _on_level_up(floor_idx : int) -> void: 36 | self.set_floor(floor_idx) 37 | -------------------------------------------------------------------------------- /entities/hellevator.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=2] 2 | 3 | [ext_resource path="res://scripts/hellevator.gd" type="Script" id=1] 4 | [ext_resource path="res://sprites/helevator_door.png" type="Texture" id=2] 5 | [ext_resource path="res://sprites/pillar.png" type="Texture" id=3] 6 | [ext_resource path="res://sounds/elevator_ride.wav" type="AudioStream" id=4] 7 | [ext_resource path="res://sounds/elevator_arrived.wav" type="AudioStream" id=5] 8 | 9 | [node name="Hellevator" type="Node2D"] 10 | script = ExtResource( 1 ) 11 | 12 | [node name="HellevatorDoor" type="Sprite" parent="."] 13 | position = Vector2( -12, 92 ) 14 | texture = ExtResource( 2 ) 15 | centered = false 16 | region_enabled = true 17 | region_rect = Rect2( 600, 0, 600, 600 ) 18 | 19 | [node name="LeftPillar" type="Sprite" parent="."] 20 | position = Vector2( -15, 386 ) 21 | texture = ExtResource( 3 ) 22 | 23 | [node name="RightPillar" type="Sprite" parent="."] 24 | position = Vector2( 591, 386 ) 25 | texture = ExtResource( 3 ) 26 | 27 | [node name="ElevatorArrivedStream" type="AudioStreamPlayer2D" parent="."] 28 | position = Vector2( 300, 300 ) 29 | stream = ExtResource( 5 ) 30 | bus = "SoundEffects" 31 | 32 | [node name="ElevatorRideStream" type="AudioStreamPlayer2D" parent="."] 33 | position = Vector2( 300, 300 ) 34 | stream = ExtResource( 4 ) 35 | bus = "SoundEffects" 36 | -------------------------------------------------------------------------------- /entities/elevator_operator.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=2] 2 | 3 | [ext_resource path="res://sprites/elevator_operator.png" type="Texture" id=1] 4 | [ext_resource path="res://sprites/speech_bubble.png" type="Texture" id=2] 5 | [ext_resource path="res://scripts/elevator_operator.gd" type="Script" id=3] 6 | 7 | [sub_resource type="DynamicFontData" id=1] 8 | font_path = "res://fonts/ComicNeue-Regular.ttf" 9 | 10 | [sub_resource type="DynamicFont" id=2] 11 | size = 30 12 | font_data = SubResource( 1 ) 13 | 14 | [node name="ElevatorOperator" type="Node2D"] 15 | position = Vector2( 720.813, 172.194 ) 16 | script = ExtResource( 3 ) 17 | __meta__ = { 18 | "_edit_group_": true 19 | } 20 | 21 | [node name="Sprite" type="Sprite" parent="."] 22 | position = Vector2( 0, 332 ) 23 | texture = ExtResource( 1 ) 24 | hframes = 2 25 | 26 | [node name="SpeechSprite" type="Sprite" parent="."] 27 | visible = false 28 | position = Vector2( -390.478, 45.0729 ) 29 | texture = ExtResource( 2 ) 30 | 31 | [node name="Label" type="Label" parent="SpeechSprite"] 32 | margin_left = -143.0 33 | margin_top = -131.0 34 | margin_right = 149.0 35 | margin_bottom = 127.0 36 | custom_fonts/font = SubResource( 2 ) 37 | custom_colors/font_color = Color( 0, 0, 0, 1 ) 38 | text = "Texty text text text" 39 | autowrap = true 40 | __meta__ = { 41 | "_edit_use_anchors_": false 42 | } 43 | -------------------------------------------------------------------------------- /entities/move_button.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=2] 2 | 3 | [ext_resource path="res://sprites/moves.png" type="Texture" id=1] 4 | [ext_resource path="res://sprites/move_select_outline.png" type="Texture" id=2] 5 | [ext_resource path="res://scripts/move_button.gd" type="Script" id=3] 6 | [ext_resource path="res://sounds/select_move_index.wav" type="AudioStream" id=4] 7 | 8 | [sub_resource type="RectangleShape2D" id=1] 9 | extents = Vector2( 32, 32 ) 10 | 11 | [node name="MoveButton" type="Node2D"] 12 | script = ExtResource( 3 ) 13 | __meta__ = { 14 | "_edit_group_": true 15 | } 16 | 17 | [node name="OutlineSprite" type="Sprite" parent="."] 18 | texture = ExtResource( 2 ) 19 | hframes = 2 20 | 21 | [node name="MoveSprite" type="Sprite" parent="."] 22 | texture = ExtResource( 1 ) 23 | hframes = 7 24 | 25 | [node name="Area2D" type="Area2D" parent="."] 26 | 27 | [node name="CollisionShape2D" type="CollisionShape2D" parent="Area2D"] 28 | shape = SubResource( 1 ) 29 | 30 | [node name="ClickStream" type="AudioStreamPlayer2D" parent="."] 31 | stream = ExtResource( 4 ) 32 | bus = "SoundEffects" 33 | 34 | [connection signal="input_event" from="Area2D" to="." method="_on_click"] 35 | [connection signal="mouse_entered" from="Area2D" to="." method="_on_mouse_enter"] 36 | [connection signal="mouse_exited" from="Area2D" to="." method="_on_mouse_leave"] 37 | -------------------------------------------------------------------------------- /scripts/main_scene.gd: -------------------------------------------------------------------------------- 1 | extends Camera2D 2 | 3 | 4 | var decay = 2 # How quickly the shaking stops 5 | var max_offset = Vector2(100, 75) # Maximum hor/ver shake in pixels. 6 | var max_roll = 0.1 # Maximum rotation in radians (use sparingly). 7 | var trauma = 0.0 # Current shake strength. 8 | 9 | 10 | # Called when the node enters the scene tree for the first time. 11 | func _ready(): 12 | LogicManager.connect("enemy_death", self, "_enemy_death") 13 | LogicManager.connect("on_combo", self, "_on_combo") 14 | LogicManager.connect("on_button_press", self, "_on_button_press") 15 | 16 | 17 | # Called every frame. 'delta' is the elapsed time since the previous frame. 18 | func _process(delta): 19 | trauma = min(trauma, 0.8) 20 | trauma = max(trauma - decay * delta, 0) 21 | if trauma > 0: 22 | shake() 23 | 24 | func shake(): 25 | var amount = trauma * trauma 26 | rotation = max_roll * amount * rand_range(-1, 1) 27 | offset.x = max_offset.x * amount * rand_range(-1, 1) 28 | offset.y = max_offset.y * amount * rand_range(-1, 1) 29 | 30 | func _enemy_death(idx : int, ipos : IntVec2) -> void: 31 | if LogicManager.should_level_up(): 32 | return 33 | trauma += 0.0 # screen shake doesn't really work with the sound effect 34 | 35 | func _on_button_press(idx : int) -> void: 36 | decay = 2 37 | trauma += 0.3 38 | 39 | 40 | func on_damage() -> void: 41 | # called from pawn.gd 42 | decay = 1.3 43 | trauma += 0.6 44 | 45 | func _on_combo(ipos : IntVec2, count : int) -> void: 46 | decay = 2 47 | trauma += 0.1 + count * 0.2 48 | -------------------------------------------------------------------------------- /scripts/board_button.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const ChessBoard := preload("res://scripts/chessboard.gd") 4 | 5 | var ipos := IntVec2.new(0, 0) 6 | var parent : Node = null 7 | var death_timer := 0.0 8 | onready var board : ChessBoard = get_tree().get_root().find_node("ChessBoard", true, false) 9 | onready var outline_sprite := $Sprite 10 | 11 | func _ready() -> void: 12 | self.position = self.board.get_pos(self.ipos) 13 | self.parent.connect("start_select_move_index", self, "_start_select_move_index") 14 | self.parent.connect("start_select_move_target", self, "_start_select_move_target") 15 | self.parent.connect("finish_select_move", self, "_finish_select_move") 16 | 17 | func _process(delta : float) -> void: 18 | if death_timer != 0.0: 19 | death_timer -= delta 20 | if death_timer <= 0.0: 21 | queue_free() 22 | 23 | func _on_click(obj : Node, event : InputEvent, idx : int) -> void: 24 | if event is InputEventMouseButton && event.pressed && event.button_index == BUTTON_LEFT: 25 | self.parent.move_target_click_stream.play() 26 | self.parent.select_move_target(self.ipos) 27 | 28 | func _on_mouse_enter() -> void: 29 | self.outline_sprite.frame = 1 30 | 31 | func _on_mouse_leave() -> void: 32 | self.outline_sprite.frame = 0 33 | 34 | func _start_select_move_index() -> void: 35 | queue_free() 36 | 37 | func _start_select_move_target() -> void: 38 | pass 39 | 40 | func _finish_select_move(index : int, target : IntVec2) -> void: 41 | if self.ipos.equals(target): 42 | death_timer = 0.1 43 | outline_sprite.frame = 1 44 | else: 45 | queue_free() 46 | -------------------------------------------------------------------------------- /scripts/hellevator.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | onready var hellevator_sprite := $HellevatorDoor 4 | 5 | const STATE_WAIT := 0 6 | const STATE_CLOSE := 1 7 | const STATE_WAIT_OPEN := 2 8 | const STATE_OPEN := 3 9 | const HELLEVATOR_DOOR_TIME := 1.2 10 | const HELLEVATOR_DOOR_WAIT_TIME := 1.5 11 | var hellevator_timer := 0.0 12 | var state = STATE_WAIT 13 | onready var arrive_stream := $ElevatorArrivedStream 14 | onready var travel_stream := $ElevatorRideStream 15 | 16 | func _process(delta : float) -> void: 17 | if self.state == STATE_OPEN: 18 | hellevator_timer += delta 19 | self.hellevator_sprite.region_rect.position.x = 600 - 600*sin(0.5*PI*(hellevator_timer / HELLEVATOR_DOOR_TIME)) 20 | if hellevator_timer > HELLEVATOR_DOOR_TIME: 21 | self.hellevator_timer = 0.0 22 | self.hellevator_sprite.region_rect.position.x = 0 23 | self.state = STATE_WAIT_OPEN 24 | self.travel_stream.play() 25 | elif self.state == STATE_WAIT_OPEN: 26 | hellevator_timer += delta 27 | if hellevator_timer > HELLEVATOR_DOOR_WAIT_TIME: 28 | self.state = STATE_CLOSE 29 | self.hellevator_timer = 0.0 30 | elif self.state == STATE_CLOSE: 31 | hellevator_timer += delta 32 | self.hellevator_sprite.region_rect.position.x = 600*(1 - cos(0.5*PI*(hellevator_timer / HELLEVATOR_DOOR_TIME))) 33 | if hellevator_timer > HELLEVATOR_DOOR_TIME: 34 | self.hellevator_timer = 0.0 35 | self.hellevator_sprite.region_rect.position.x = 600 36 | self.state = STATE_WAIT 37 | 38 | func _open_door() -> void: 39 | self.state = STATE_OPEN 40 | if self.arrive_stream: 41 | self.arrive_stream.play() 42 | -------------------------------------------------------------------------------- /dialogue: -------------------------------------------------------------------------------- 1 | So you've got a problem with the rules of chess? 2 | You think that pawns like you should be able to move willy-nilly where-ever they please? 3 | Well that's the type of thinking that got you sent here. Hell. 4 | Pawns should move forward, once square at a time. 5 | If another piece is in the way, they get stuck. 6 | And they can only attack diagonally, a maximum of one square! 7 | If you've got a problem with those rules, take it up with the Queen. 8 | Now, Hell-pawns, attack! 9 | 10 | You know you're not special. All pieces can break the rules, but the rules are in place for the good of all. 11 | A pawn like you makes up the front line of attack. Your role is to break the enemy's line of defense with your life. 12 | Just like my role is to defend the Queen's private elevator. 13 | 14 | Perhaps you rebel because you think pawns are weak. Well you couldn't be further from the truth. 15 | Individually, pawns are weak, but in a strong formation, pawns are unstoppable. 16 | Each pawn protects its neighbours for the good of the line. 17 | 18 | What do you think will happen when this elevator reaches the last floor? 19 | Do you think the Queen will listen to the arguments of a pawn? 20 | The Queen will punish you and me both. 21 | 22 | How can a lowly pawn defy destiny, while the Queen's most distinguished elevator operator cannot? 23 | Will I be defeated? 24 | No! I know how every chess piece is permitted to move! I know the strengths and weaknesses of every pawn formation! 25 | Hell-pawns, show this renegade the meaning of true pawn power. 26 | 27 | 28 | My Queen... 29 | 30 | Why is my chess game being interupted by this elevator operator and his pawn? 31 | Throw the elevator operator into the magma pits. 32 | As for this pawn, I will show it why Queen's have the right to rule. 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | _global_script_classes=[ { 12 | "base": "Object", 13 | "class": "ButtonLogic", 14 | "language": "GDScript", 15 | "path": "res://scripts/button_logic.gd" 16 | }, { 17 | "base": "Object", 18 | "class": "IntVec2", 19 | "language": "GDScript", 20 | "path": "res://scripts/intvec2.gd" 21 | }, { 22 | "base": "Reference", 23 | "class": "MoveType", 24 | "language": "GDScript", 25 | "path": "res://scripts/move_type.gd" 26 | }, { 27 | "base": "Object", 28 | "class": "PawnFormationFactory", 29 | "language": "GDScript", 30 | "path": "res://scripts/pawn_formation_factory.gd" 31 | }, { 32 | "base": "Reference", 33 | "class": "Phases", 34 | "language": "GDScript", 35 | "path": "res://scripts/phases.gd" 36 | }, { 37 | "base": "Object", 38 | "class": "PieceLogic", 39 | "language": "GDScript", 40 | "path": "res://scripts/piece_logic.gd" 41 | } ] 42 | _global_script_class_icons={ 43 | "ButtonLogic": "", 44 | "IntVec2": "", 45 | "MoveType": "", 46 | "PawnFormationFactory": "", 47 | "Phases": "", 48 | "PieceLogic": "" 49 | } 50 | 51 | [application] 52 | 53 | config/name="Chesstris" 54 | run/main_scene="res://levels/menu.tscn" 55 | config/icon="res://icon.png" 56 | 57 | [autoload] 58 | 59 | LogicManager="*res://scripts/logic_manager.gd" 60 | MusicController="*res://entities/music_controller.tscn" 61 | DialogueManager="*res://scripts/dialogue_manager.gd" 62 | 63 | [display] 64 | 65 | window/size/width=960 66 | 67 | [physics] 68 | 69 | common/enable_pause_aware_picking=true 70 | 71 | [rendering] 72 | 73 | quality/driver/driver_name="GLES2" 74 | vram_compression/import_etc=true 75 | vram_compression/import_etc2=false 76 | environment/default_environment="res://default_env.tres" 77 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # 3D models 2 | *.3dm filter=lfs diff=lfs merge=lfs -text 3 | *.3ds filter=lfs diff=lfs merge=lfs -text 4 | *.blend filter=lfs diff=lfs merge=lfs -text 5 | *.c4d filter=lfs diff=lfs merge=lfs -text 6 | *.collada filter=lfs diff=lfs merge=lfs -text 7 | *.dae filter=lfs diff=lfs merge=lfs -text 8 | *.dxf filter=lfs diff=lfs merge=lfs -text 9 | *.fbx filter=lfs diff=lfs merge=lfs -text 10 | *.jas filter=lfs diff=lfs merge=lfs -text 11 | *.lws filter=lfs diff=lfs merge=lfs -text 12 | *.lxo filter=lfs diff=lfs merge=lfs -text 13 | *.ma filter=lfs diff=lfs merge=lfs -text 14 | *.max filter=lfs diff=lfs merge=lfs -text 15 | *.mb filter=lfs diff=lfs merge=lfs -text 16 | *.obj filter=lfs diff=lfs merge=lfs -text 17 | *.ply filter=lfs diff=lfs merge=lfs -text 18 | *.skp filter=lfs diff=lfs merge=lfs -text 19 | *.stl filter=lfs diff=lfs merge=lfs -text 20 | *.ztl filter=lfs diff=lfs merge=lfs -text 21 | # Audio 22 | *.aif filter=lfs diff=lfs merge=lfs -text 23 | *.aiff filter=lfs diff=lfs merge=lfs -text 24 | *.it filter=lfs diff=lfs merge=lfs -text 25 | *.mod filter=lfs diff=lfs merge=lfs -text 26 | *.mp3 filter=lfs diff=lfs merge=lfs -text 27 | *.ogg filter=lfs diff=lfs merge=lfs -text 28 | *.s3m filter=lfs diff=lfs merge=lfs -text 29 | *.wav filter=lfs diff=lfs merge=lfs -text 30 | *.xm filter=lfs diff=lfs merge=lfs -text 31 | # Fonts 32 | *.otf filter=lfs diff=lfs merge=lfs -text 33 | *.ttf filter=lfs diff=lfs merge=lfs -text 34 | # Images 35 | *.bmp filter=lfs diff=lfs merge=lfs -text 36 | *.exr filter=lfs diff=lfs merge=lfs -text 37 | *.gif filter=lfs diff=lfs merge=lfs -text 38 | *.hdr filter=lfs diff=lfs merge=lfs -text 39 | *.iff filter=lfs diff=lfs merge=lfs -text 40 | *.jpeg filter=lfs diff=lfs merge=lfs -text 41 | *.jpg filter=lfs diff=lfs merge=lfs -text 42 | *.pict filter=lfs diff=lfs merge=lfs -text 43 | *.png filter=lfs diff=lfs merge=lfs -text 44 | *.psd filter=lfs diff=lfs merge=lfs -text 45 | *.tga filter=lfs diff=lfs merge=lfs -text 46 | *.tif filter=lfs diff=lfs merge=lfs -text 47 | *.tiff filter=lfs diff=lfs merge=lfs -text 48 | 49 | -------------------------------------------------------------------------------- /levels/main.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=11 format=2] 2 | 3 | [ext_resource path="res://entities/chessboard.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://entities/player.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://entities/controller.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://entities/move_button.tscn" type="PackedScene" id=4] 7 | [ext_resource path="res://entities/move_display.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://entities/floor_indicator.tscn" type="PackedScene" id=6] 9 | [ext_resource path="res://sprites/next_move.png" type="Texture" id=7] 10 | [ext_resource path="res://scripts/main_scene.gd" type="Script" id=8] 11 | [ext_resource path="res://entities/hellevator.tscn" type="PackedScene" id=9] 12 | [ext_resource path="res://backgrounds/background.png" type="Texture" id=10] 13 | 14 | [node name="Main" type="Camera2D"] 15 | anchor_mode = 0 16 | current = true 17 | script = ExtResource( 8 ) 18 | 19 | [node name="Controller" parent="." instance=ExtResource( 3 )] 20 | 21 | [node name="Background" type="Sprite" parent="."] 22 | texture = ExtResource( 10 ) 23 | centered = false 24 | 25 | [node name="ChessBoard" parent="." instance=ExtResource( 1 )] 26 | position = Vector2( 62, -75 ) 27 | 28 | [node name="BoardButtons" type="Node2D" parent="."] 29 | 30 | [node name="Buttons" type="Node2D" parent="."] 31 | 32 | [node name="Pawns" type="Node2D" parent="."] 33 | 34 | [node name="Player" parent="." instance=ExtResource( 2 )] 35 | position = Vector2( 860.677, 142.592 ) 36 | 37 | [node name="Effects" type="Node2D" parent="."] 38 | 39 | [node name="Hellevator" parent="." instance=ExtResource( 9 )] 40 | position = Vector2( 62, -75 ) 41 | 42 | [node name="FloorIndicator" parent="." instance=ExtResource( 6 )] 43 | position = Vector2( 818.164, 174.84 ) 44 | 45 | [node name="NextMoveSprite" type="Sprite" parent="."] 46 | position = Vector2( 878.181, 343.563 ) 47 | texture = ExtResource( 7 ) 48 | 49 | [node name="MoveButton" parent="." instance=ExtResource( 4 )] 50 | position = Vector2( 740, 307 ) 51 | 52 | [node name="MoveButton2" parent="." instance=ExtResource( 4 )] 53 | position = Vector2( 740, 417 ) 54 | index = 1 55 | 56 | [node name="MoveButton3" parent="." instance=ExtResource( 4 )] 57 | position = Vector2( 740, 527 ) 58 | index = 2 59 | 60 | [node name="MoveDisplay" parent="." instance=ExtResource( 5 )] 61 | position = Vector2( 875.081, 437.49 ) 62 | -------------------------------------------------------------------------------- /scripts/elevator_operator.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | export(Array, String) var text := [ 4 | "Blah blah blah I am saying things to test but what gotta make this long for testing purposes!", 5 | "AM I REALLY TALKING??" 6 | ] 7 | 8 | const STATE_ARRIVING := 0 9 | const STATE_SCROLLING := 1 10 | const STATE_WAITING := 2 11 | const STATE_LEAVING := 3 12 | 13 | const START_Y := 800.0 14 | const END_Y := 200.0 15 | const TRAVEL_TIME := 0.75 16 | const FRAMES_PER_LETTER := 2 17 | 18 | var immune := false 19 | var immune_timer := 0.0 20 | var timer := 0.0 21 | var state := STATE_ARRIVING 22 | var index := 0 23 | var frame := 0 24 | onready var label := $SpeechSprite/Label 25 | onready var sprite := $Sprite 26 | onready var speech_sprite := $SpeechSprite 27 | 28 | signal done_talking() 29 | 30 | func _ready() -> void: 31 | self.label.text = "" 32 | self.position.y = 700 33 | 34 | func _input(event : InputEvent) -> void: 35 | get_tree().set_input_as_handled() 36 | if !self.immune && event is InputEventMouseButton && event.pressed && event.button_index == BUTTON_LEFT: 37 | if self.state == STATE_SCROLLING: 38 | self.label.text = self.text[self.index] 39 | self.state = STATE_WAITING 40 | self.timer = 0.0 41 | elif self.state == STATE_WAITING: 42 | self.index += 1 43 | self.label.text = "" 44 | if self.index >= self.text.size(): 45 | self.state = STATE_LEAVING 46 | self.speech_sprite.visible = false 47 | else: 48 | self.state = STATE_SCROLLING 49 | self.timer = 0.0 50 | 51 | func _process(delta : float) -> void: 52 | timer += delta 53 | if self.immune: 54 | immune_timer -= delta 55 | if self.immune_timer < 0.0: 56 | self.immune = false 57 | if self.state == STATE_ARRIVING: 58 | self.position.y = START_Y + (END_Y - START_Y) * sin(0.5*PI*(timer/TRAVEL_TIME)) 59 | if timer > TRAVEL_TIME: 60 | self.timer = 0.0 61 | self.index = 0 62 | self.state = STATE_SCROLLING 63 | self.position.y = END_Y 64 | self.speech_sprite.visible = true 65 | elif self.state == STATE_SCROLLING: 66 | self.frame += 1 67 | if self.frame == FRAMES_PER_LETTER: 68 | self.frame = 0 69 | if self.label.text.length() == self.text[self.index].length(): 70 | self.state = STATE_WAITING 71 | self.timer = 0.0 72 | self.immune = true 73 | self.immune_timer = 0.2 74 | else: 75 | self.label.text += self.text[self.index][self.label.text.length()] 76 | elif self.state == STATE_WAITING: 77 | pass 78 | elif self.state == STATE_LEAVING: 79 | self.position.y = END_Y + (START_Y - END_Y) * (1.0 - cos(0.5*PI*(timer/TRAVEL_TIME))) 80 | if timer > TRAVEL_TIME: 81 | emit_signal("done_talking") 82 | queue_free() 83 | -------------------------------------------------------------------------------- /scripts/pawn_formation_factory.gd: -------------------------------------------------------------------------------- 1 | extends Object 2 | 3 | class_name PawnFormationFactory 4 | 5 | # Formation Templates 6 | const EMPTY = [] 7 | const SINGLE = [[1]] 8 | const H_PAIR = [[1,1]] 9 | const D_PAIR1 = [[1,0],[0,1]] 10 | const D_PAIR2 = [[0,1],[1,0]] 11 | const V = [[1,0,1],[0,1,0]] 12 | const EYES = [[1,0,0,0,0,1]] 13 | const CLOSE_EYES = [[1,0,0,1]] 14 | const CLOSEST_EYES = [[1,0,1]] 15 | const INVERT_V = [[0,1,0],[1,0,1]] 16 | const UHOH = [[0,1,0,1,0,1],[1,0,1,0,1,0]] 17 | const TALL = [[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]] 18 | const TALL2 = [[0,0,0,1],[0,0,1,0],[0,1,0,0],[1,0,0,0]] 19 | const LINE = [[1],[1]] 20 | const LONG_LINE = [[1],[1],[1]] 21 | const SIXV = [[1,0,0,0,0,1],[0,1,0,0,1,0],[0,0,1,1,0,0]] 22 | const QUATRO = [[1,0,1],[1,0,1]] 23 | const FULL_LINE = [[1,1,1,1,1,1]] 24 | 25 | const ALL_BAG = [SINGLE,H_PAIR,D_PAIR1,D_PAIR2,V,EYES,INVERT_V,UHOH] 26 | 27 | const LEVEL = { 28 | 0: { 29 | 'bag': [SINGLE], 30 | 'time_between_new': 1 31 | }, 32 | 1: { 33 | 'bag': [SINGLE, H_PAIR, D_PAIR1, D_PAIR2, EYES, LINE], 34 | 'time_between_new': 1 35 | }, 36 | 2: { 37 | 'bag': [V, INVERT_V, EYES, CLOSE_EYES, LONG_LINE], 38 | 'time_between_new': 1, 39 | }, 40 | 3: { 41 | 'bag': [TALL, TALL2, QUATRO], 42 | 'time_between_new': 0 43 | }, 44 | 4: { 45 | 'bag': [UHOH, SIXV], 46 | 'time_between_new': 0 47 | }, 48 | 5: { 49 | 'bag': [FULL_LINE], 50 | 'time_between_new': -6 51 | } 52 | } 53 | 54 | var spawn_row # pieces always spawn at this row or above (never below) 55 | var row_width 56 | 57 | var _prev_level := 0 58 | var _turns_until_next_spawn := 0 59 | 60 | func _init(spawn_row_ : int, row_width_ : int) -> void: 61 | self.spawn_row = spawn_row_ 62 | self.row_width = row_width_ 63 | 64 | func generate(level: int, turn: int) -> Array: 65 | var formation = [] 66 | if level != _prev_level: 67 | _prev_level = level 68 | _turns_until_next_spawn = 0 69 | if _turns_until_next_spawn <= 0: 70 | var lvl = LEVEL[level] 71 | if level == 2: 72 | lvl.time_between_new = (lvl.time_between_new + 1) % 2 73 | 74 | formation = _prep_formation(lvl.bag[randi() % lvl.bag.size()]) 75 | _turns_until_next_spawn = formation.size() + lvl.time_between_new 76 | else: 77 | _turns_until_next_spawn = _turns_until_next_spawn - 1 78 | return formation 79 | 80 | func _prep_formation(template: Array) -> Array: 81 | var positions = [] 82 | if template.size() == 0: 83 | return positions 84 | var width = template[0].size() 85 | var height = template.size() 86 | var max_x_offset = max(0, row_width - width) 87 | var x_offset = randi() % (max_x_offset + 1) 88 | for y in range(0, height): 89 | for x in range(0, width): 90 | if template[y][x] == 1: 91 | positions.push_back( 92 | IntVec2.new(x_offset + x, spawn_row + height - y) 93 | ) 94 | return positions 95 | 96 | -------------------------------------------------------------------------------- /scripts/dialogue_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | const ElevatorOperatorScene := preload("res://entities/elevator_operator.tscn") 4 | 5 | var in_dialogue := false 6 | var seen_tip := false 7 | 8 | var said_level_dialogue := [false, false, false, false, false, false, false] 9 | var level_dialgoue := [ 10 | [ 11 | "So you've got a problem with the rules of chess?", 12 | "You think that pawns like you should be able to move willy-nilly where-ever they please?", 13 | "Well that's the type of thinking that got you sent here. Hell.", 14 | "Pawns should move forward, one square at a time.", 15 | "If another piece is in the way, they get stuck.", 16 | "And they can only attack diagonally, a maximum of one square!", 17 | "If you've got a problem with those rules, take it up with the Queen.", 18 | "Now, Hell-pawns, attack!" 19 | ], 20 | [ 21 | "You know you're not special. All pieces can break the rules, but the rules are in place for the good of all.", 22 | "A pawn like you makes up the front line of attack.", 23 | "Your role is to break the enemy's line of defense with your life.", 24 | "Just like my role is to defend the Queen's private elevator." 25 | ], 26 | [ 27 | "Perhaps you rebel because you think pawns are weak. Well you couldn't be further from the truth.", 28 | "Individually, pawns are weak, but in a strong formation, pawns are unstoppable.", 29 | "Each pawn protects its neighbours for the good of the line." 30 | ], 31 | [ 32 | "What do you think will happen when this elevator reaches the last floor?", 33 | "Do you think the Queen will listen to the arguments of a pawn?", 34 | "The Queen will punish you and me both." 35 | ], 36 | [ 37 | "How can a lowly pawn defy destiny, while the Queen's most distinguished elevator operator cannot?", 38 | "Will I be defeated?", 39 | "No! I know how every chess piece is permitted to move!", 40 | "I know the strengths and weaknesses of every pawn formation!", 41 | "Hell-pawns, show this renegade the meaning of true pawn power." 42 | ], 43 | [ 44 | "Why is my chess game being interupted by this elevator operator and his pawn?", 45 | "Throw the elevator operator into the magma pits.", 46 | "As for this pawn, I will show it why Queens have the right to rule." 47 | ], 48 | [ 49 | "No! My sisters... You killed them all!", 50 | "Now you will pay.", 51 | "Uh... no... I am slain as well. You win." 52 | ] 53 | ] 54 | 55 | func _ready() -> void: 56 | LogicManager.connect("on_level_up", self, "_on_level_up") 57 | 58 | func say_dialogue(dialogue : Array, queen := false) -> void: 59 | var operator := ElevatorOperatorScene.instance() 60 | operator.text = dialogue 61 | var root : Node = get_tree().get_root() 62 | root.add_child(operator) 63 | if queen: 64 | operator.sprite.frame = 1 65 | self.in_dialogue = true 66 | operator.connect("done_talking", self, "_dialogue_over") 67 | 68 | func _dialogue_over() -> void: 69 | self.in_dialogue = false 70 | -------------------------------------------------------------------------------- /scripts/move_button.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const Player := preload("res://scripts/player.gd") 4 | 5 | export var index := 0 6 | var disabled := false 7 | var active := false 8 | onready var player : Player = get_tree().get_root().find_node("Player", true, false) 9 | onready var move_sprite := $MoveSprite 10 | onready var outline_sprite := $OutlineSprite 11 | onready var click_stream := $ClickStream 12 | 13 | func _convert_move_sprite_index(idx : int) -> int: 14 | if idx == MoveType.GOOD_PAWN: 15 | return 0 16 | elif idx == MoveType.KNIGHT: 17 | return 1 18 | elif idx == MoveType.BISHOP: 19 | return 2 20 | elif idx == MoveType.ROOK: 21 | return 3 22 | elif idx == MoveType.QUEEN: 23 | return 4 24 | elif idx == MoveType.KING: 25 | return 5 26 | else: 27 | print("Invalid move index") 28 | get_tree().quit() 29 | return 0 30 | 31 | func _ready() -> void: 32 | self.move_sprite.frame = _convert_move_sprite_index(LogicManager.moves[self.index]) 33 | player.connect("start_select_move_index", self, "_start_select_move_index") 34 | player.connect("start_select_move_target", self, "_start_select_move_target") 35 | player.connect("finish_select_move", self, "_finish_select_move") 36 | LogicManager.connect("move_draw", self, "_move_draw") 37 | LogicManager.connect("on_damage", self, "_on_damage") 38 | LogicManager.connect("on_life_up", self, "_on_life_up") 39 | 40 | func _move_draw(type : int, slot : int, next_move : int) -> void: 41 | if not self.disabled: 42 | if self.index == slot: 43 | self.move_sprite.frame = _convert_move_sprite_index(LogicManager.moves[self.index]) 44 | self.outline_sprite.frame = 0 45 | 46 | func _on_click(obj : Node, event : InputEvent, idx : int) -> void: 47 | if event is InputEventMouseButton && event.pressed && event.button_index == BUTTON_LEFT: 48 | if not disabled && self.active: 49 | player.select_move_index(self.index) 50 | self.click_stream.play() 51 | elif player.state == player.STATE_SELECT_MOVE_TARGET: 52 | player.undo_select_move_index() 53 | player.select_move_index(self.index) 54 | self.click_stream.play() 55 | 56 | func _on_mouse_enter() -> void: 57 | if not self.disabled && self.active: 58 | self.outline_sprite.frame = 1 59 | 60 | func _on_mouse_leave() -> void: 61 | if not self.disabled && self.active: 62 | self.outline_sprite.frame = 0 63 | 64 | func _start_select_move_index() -> void: 65 | if not self.disabled: 66 | self.active = true 67 | self.outline_sprite.frame = 0 68 | 69 | func _start_select_move_target(move_index : int) -> void: 70 | if not self.disabled: 71 | if self.index == move_index: 72 | self.outline_sprite.frame = 1 73 | self.active = false 74 | 75 | func _on_damage(id, ipos, lives) -> void: 76 | if lives <= self.index: 77 | self.disabled = true 78 | self.active = false 79 | self.move_sprite.frame = 6 80 | 81 | func _on_life_up(lives) -> void: 82 | if lives > self.index: 83 | self.disabled = false 84 | self.active = true 85 | self.move_sprite.frame = _convert_move_sprite_index(LogicManager.moves[self.index]) 86 | -------------------------------------------------------------------------------- /scripts/pawn.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const ChessBoard := preload("res://scripts/chessboard.gd") 4 | const QueenTexture := preload("res://sprites/queen.png") 5 | const HurtFlashInstance := preload("res://entities/hurt_flash.tscn") 6 | 7 | const PLACE_TIME := 0.1 8 | 9 | const STATE_PAWN := 0 10 | const STATE_QUEEN := 1 11 | 12 | var idx := 0 13 | var hurt := false 14 | var kill := false 15 | var dying := false 16 | var state := STATE_PAWN 17 | var ipos := IntVec2.new(0, 0) 18 | var target_pos : Vector2 19 | onready var sprite := $Sprite 20 | onready var enemy_death_stream := $EnemyDeathStream 21 | onready var board : ChessBoard = get_tree().get_root().find_node("ChessBoard", true, false) 22 | onready var effects : Node2D = get_tree().get_root().find_node("Effects", true, false) 23 | onready var scene = get_tree().get_root().find_node("Main", true, false) 24 | onready var player = get_tree().get_root().find_node("Player", true, false) 25 | 26 | func _ready() -> void: 27 | self.target_pos = board.get_pos(self.ipos) 28 | self.position = self.target_pos 29 | LogicManager.connect("move_enemy", self, "_logic_move") 30 | LogicManager.connect("enemy_death", self, "_logic_death") 31 | LogicManager.connect("pawn_promotion", self, "_logic_promotion") 32 | LogicManager.connect("on_damage", self, "_logic_on_damage") 33 | 34 | func _process(delta : float) -> void: 35 | if self.dying: 36 | self.position += 1000 * self.target_pos * delta 37 | self.target_pos.y += 2 * delta 38 | self.rotation_degrees += 360 * delta 39 | self.scale *= exp(-delta / 3.0) 40 | if self.position.y > 2000: 41 | queue_free() 42 | else: 43 | if self.target_pos != self.position: 44 | var delta_pos := self.position - self.target_pos 45 | if delta_pos.length_squared() <= 10: 46 | self.position = self.target_pos 47 | if self.hurt: 48 | var hurt_flash : Node2D = HurtFlashInstance.instance() 49 | self.effects.add_child(hurt_flash) 50 | hurt_flash.position = self.position 51 | scene.on_damage() 52 | if self.kill: 53 | player._on_kill() 54 | else: 55 | queue_free() 56 | 57 | else: 58 | self.position = self.target_pos + delta_pos * exp(-delta / PLACE_TIME) 59 | 60 | func _logic_move(idx : int, ipos : IntVec2) -> void: 61 | if idx == self.idx: 62 | self.target_pos = board.get_pos(ipos) 63 | 64 | func _logic_death(idx : int, ipos : IntVec2) -> void: 65 | if idx == self.idx: 66 | self.dying = true 67 | var angle = randf() * 2 * PI 68 | self.target_pos = Vector2(cos(angle), sin(angle)) 69 | if not LogicManager.should_level_up(): 70 | # avoid playing the death sound on level up 71 | # because if many enemies die at once it can get kinda glitchy 72 | self.enemy_death_stream.play() 73 | 74 | func _logic_promotion(idx : int, ipos : IntVec2) -> void: 75 | if idx == self.idx: 76 | self.state = STATE_QUEEN 77 | sprite.texture = QueenTexture 78 | 79 | func _logic_on_damage(idx : int, ipos : IntVec2, life : int) -> void: 80 | if idx == self.idx: 81 | self.target_pos = board.get_pos(ipos) 82 | self.hurt = true 83 | if life == 0: 84 | self.kill = true 85 | -------------------------------------------------------------------------------- /scripts/controller.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const ChessBoard := preload("res://scripts/chessboard.gd") 4 | const PawnScene := preload("res://entities/pawn.tscn") 5 | const ElevatorButtonScene := preload("res://entities/elevator_button.tscn") 6 | 7 | onready var board : ChessBoard = get_tree().get_root().find_node("ChessBoard", true, false) 8 | onready var hellevator = get_tree().get_root().find_node("Hellevator", true, false) 9 | onready var pawns := get_tree().get_root().find_node("Pawns", true, false) 10 | onready var buttons := get_tree().get_root().find_node("Buttons", true, false) 11 | 12 | const TIME_PER_PHASE := 0.1 13 | const GAME_OVER_TIME := 2.0 14 | const YOU_WIN_TIME := 2.0 15 | 16 | var phase_timer := 0.0 17 | var finishing_level := false 18 | var losing := false 19 | var winning := false 20 | 21 | func _ready() -> void: 22 | LogicManager.connect("spawn_enemy", self, "_logic_spawn") 23 | LogicManager.connect("on_button_create", self, "_logic_create_button") 24 | LogicManager.connect("on_level_up", self, "_logic_level_up") 25 | LogicManager.reset() 26 | 27 | func _logic_level_up(level : int) -> void: 28 | hellevator._open_door() 29 | self.finishing_level = true 30 | 31 | func _process(delta : float) -> void: 32 | if !DialogueManager.in_dialogue && losing: 33 | get_tree().change_scene("res://levels/gameover.tscn") 34 | elif !DialogueManager.in_dialogue && winning: 35 | get_tree().change_scene("res://levels/youwin.tscn") 36 | elif self.finishing_level: 37 | if hellevator.state == hellevator.STATE_WAIT: 38 | self.finishing_level = false 39 | if !DialogueManager.said_level_dialogue[LogicManager.level]: 40 | DialogueManager.said_level_dialogue[LogicManager.level] = true 41 | DialogueManager.say_dialogue(DialogueManager.level_dialgoue[LogicManager.level], LogicManager.level >= 5) 42 | elif LogicManager.phase == Phases.PRE_GAME: 43 | LogicManager.increment_phase() 44 | elif LogicManager.phase == Phases.GAME_OVER: 45 | phase_timer += delta 46 | if phase_timer > GAME_OVER_TIME && !losing: 47 | losing = true 48 | var dialogue := "" 49 | if LogicManager.level == 5: 50 | dialogue = ["Lowly pawn!", "Filthy pawn!", "I knew you would fall.", "The power of a queen cannot be denied.", "Get this pawn out of here!"][randi() % 5] 51 | else: 52 | dialogue = ["Pawns must obey.", "Foolish pawn.", "Fall in line.", "You could never have succeeded.", "A pawn is nothing.", "Destined to fail.", "Unworthy of the Queen.", "Obey the Queen."][randi() % 8] 53 | DialogueManager.say_dialogue([dialogue], LogicManager.level >= 5) 54 | elif LogicManager.phase == Phases.YOU_WIN: 55 | phase_timer += delta 56 | if phase_timer > YOU_WIN_TIME && !winning: 57 | winning = true 58 | if !DialogueManager.said_level_dialogue[6]: 59 | DialogueManager.said_level_dialogue[6] = true 60 | DialogueManager.say_dialogue(DialogueManager.level_dialgoue[6], true) 61 | elif LogicManager.phase != Phases.PLAYER_MOVE: 62 | phase_timer += delta 63 | if phase_timer > TIME_PER_PHASE: 64 | LogicManager.increment_phase() 65 | phase_timer = 0.0 66 | 67 | func _logic_create_button(idx : int, ipos : IntVec2) -> void: 68 | var button := ElevatorButtonScene.instance() 69 | button.index = idx 70 | button.ipos = ipos 71 | self.buttons.add_child(button) 72 | 73 | func _logic_spawn(idx : int, ipos : IntVec2) -> void: 74 | var pawn := PawnScene.instance() 75 | pawn.idx = idx 76 | pawn.ipos = ipos 77 | pawn.target_pos = board.get_pos(ipos) 78 | self.pawns.add_child(pawn) 79 | -------------------------------------------------------------------------------- /scripts/player.gd: -------------------------------------------------------------------------------- 1 | extends Node2D 2 | 3 | const ChessBoard := preload("res://scripts/chessboard.gd") 4 | const BoardButtonScene := preload("res://entities/board_button.tscn") 5 | const BonusFlashScene := preload("res://entities/bonus_flash.tscn") 6 | 7 | const PLACE_TIME := 0.1 8 | 9 | const STATE_WAIT := 0 10 | const STATE_SELECT_MOVE_INDEX := 1 11 | const STATE_SELECT_MOVE_TARGET := 2 12 | const STATE_MAKE_MOVE := 3 13 | 14 | signal start_select_move_index() 15 | signal start_select_move_target(move_idx) 16 | signal finish_select_move(move_idx, move_target) 17 | 18 | const bonus_sound := preload("res://sounds/bonus_move2.wav") 19 | const combo_sound := preload("res://sounds/combo.wav") 20 | 21 | var target_pos : Vector2 22 | var state := STATE_WAIT 23 | var selected_move_index := 0 24 | var move_index := 0 25 | var move_ipos := IntVec2.new(0, 0) 26 | onready var board : ChessBoard = get_tree().get_root().find_node("ChessBoard", true, false) 27 | onready var board_buttons := get_tree().get_root().find_node("BoardButtons", true, false) 28 | onready var move_target_click_stream := $MoveTargetClickStream 29 | onready var effects := get_tree().get_root().find_node("Effects", true, false) 30 | onready var combo_stream := $ComboStream 31 | onready var hurt_stream := $HurtStream 32 | 33 | func _ready() -> void: 34 | self.target_pos = board.get_pos(LogicManager.player.pos) 35 | self.position = self.target_pos 36 | LogicManager.connect("phase_change", self, "_phase_change") 37 | LogicManager.connect("on_damage", self, "_on_damage") 38 | LogicManager.connect("on_death", self, "_on_death") 39 | LogicManager.connect("on_combo", self, "_on_combo") 40 | 41 | func _on_death() -> void: 42 | pass#self.visible = false 43 | 44 | func _on_kill() -> void: 45 | self.visible = false 46 | 47 | func _on_damage(id, pos, life_remaining) -> void: 48 | self.hurt_stream.play() 49 | 50 | func _on_combo(ipos : IntVec2, count : int) -> void: 51 | if count == 1: 52 | self.combo_stream.stream = bonus_sound 53 | else: 54 | self.combo_stream.stream = combo_sound 55 | var bonus : Node2D = BonusFlashScene.instance() 56 | bonus.position = self.position 57 | self.combo_stream.play() 58 | self.effects.add_child(bonus) 59 | 60 | func _phase_change(new_phase : int) -> void: 61 | if new_phase == Phases.PLAYER_MOVE: 62 | self.state = STATE_SELECT_MOVE_INDEX 63 | self.emit_signal("start_select_move_index") 64 | 65 | func _process(delta: float) -> void: 66 | if self.state == STATE_WAIT: 67 | pass 68 | elif self.state == STATE_MAKE_MOVE: 69 | if self.target_pos != self.position: 70 | var delta_pos := self.position - self.target_pos 71 | if delta_pos.length_squared() <= 10: 72 | self.position = self.target_pos 73 | else: 74 | self.position = self.target_pos + delta_pos * exp(-delta / PLACE_TIME) 75 | else: 76 | if not LogicManager.try_player_move(move_index, move_ipos): 77 | print("Somehow inputted an invalid move") 78 | get_tree().quit() 79 | self.state = STATE_WAIT 80 | 81 | func _input(event : InputEvent) -> void: 82 | if event is InputEventMouseButton && event.pressed && event.button_index == BUTTON_RIGHT: 83 | if self.state == STATE_SELECT_MOVE_TARGET: 84 | self.undo_select_move_index() 85 | 86 | func select_move_index(index : int) -> void: 87 | self.move_index = index 88 | # Create board buttons. 89 | var move : int = LogicManager.moves[self.move_index] 90 | var legal_moves := LogicManager.get_legal_moves(LogicManager.player.pos, move, true) 91 | for legal_move in legal_moves: 92 | var board_button := BoardButtonScene.instance() 93 | board_button.ipos = legal_move 94 | board_button.parent = self 95 | board_buttons.add_child(board_button) 96 | self.state = STATE_SELECT_MOVE_TARGET 97 | emit_signal("start_select_move_target", index) 98 | 99 | func undo_select_move_index() -> void: 100 | self.state = STATE_SELECT_MOVE_INDEX 101 | emit_signal("start_select_move_index") 102 | 103 | func select_move_target(ipos : IntVec2) -> void: 104 | self.move_ipos = ipos 105 | self.target_pos = self.board.get_pos(self.move_ipos) 106 | self.state = STATE_MAKE_MOVE 107 | emit_signal("finish_select_move", move_index, move_ipos) 108 | -------------------------------------------------------------------------------- /fonts/OFL.txt: -------------------------------------------------------------------------------- 1 | Copyright 2014 The Comic Neue Project Authors (https://github.com/crozynski/comicneue) 2 | 3 | This Font Software is licensed under the SIL Open Font License, Version 1.1. 4 | This license is copied below, and is also available with a FAQ at: 5 | http://scripts.sil.org/OFL 6 | 7 | 8 | ----------------------------------------------------------- 9 | SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 10 | ----------------------------------------------------------- 11 | 12 | PREAMBLE 13 | The goals of the Open Font License (OFL) are to stimulate worldwide 14 | development of collaborative font projects, to support the font creation 15 | efforts of academic and linguistic communities, and to provide a free and 16 | open framework in which fonts may be shared and improved in partnership 17 | with others. 18 | 19 | The OFL allows the licensed fonts to be used, studied, modified and 20 | redistributed freely as long as they are not sold by themselves. The 21 | fonts, including any derivative works, can be bundled, embedded, 22 | redistributed and/or sold with any software provided that any reserved 23 | names are not used by derivative works. The fonts and derivatives, 24 | however, cannot be released under any other type of license. The 25 | requirement for fonts to remain under this license does not apply 26 | to any document created using the fonts or their derivatives. 27 | 28 | DEFINITIONS 29 | "Font Software" refers to the set of files released by the Copyright 30 | Holder(s) under this license and clearly marked as such. This may 31 | include source files, build scripts and documentation. 32 | 33 | "Reserved Font Name" refers to any names specified as such after the 34 | copyright statement(s). 35 | 36 | "Original Version" refers to the collection of Font Software components as 37 | distributed by the Copyright Holder(s). 38 | 39 | "Modified Version" refers to any derivative made by adding to, deleting, 40 | or substituting -- in part or in whole -- any of the components of the 41 | Original Version, by changing formats or by porting the Font Software to a 42 | new environment. 43 | 44 | "Author" refers to any designer, engineer, programmer, technical 45 | writer or other person who contributed to the Font Software. 46 | 47 | PERMISSION & CONDITIONS 48 | Permission is hereby granted, free of charge, to any person obtaining 49 | a copy of the Font Software, to use, study, copy, merge, embed, modify, 50 | redistribute, and sell modified and unmodified copies of the Font 51 | Software, subject to the following conditions: 52 | 53 | 1) Neither the Font Software nor any of its individual components, 54 | in Original or Modified Versions, may be sold by itself. 55 | 56 | 2) Original or Modified Versions of the Font Software may be bundled, 57 | redistributed and/or sold with any software, provided that each copy 58 | contains the above copyright notice and this license. These can be 59 | included either as stand-alone text files, human-readable headers or 60 | in the appropriate machine-readable metadata fields within text or 61 | binary files as long as those fields can be easily viewed by the user. 62 | 63 | 3) No Modified Version of the Font Software may use the Reserved Font 64 | Name(s) unless explicit written permission is granted by the corresponding 65 | Copyright Holder. This restriction only applies to the primary font name as 66 | presented to the users. 67 | 68 | 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font 69 | Software shall not be used to promote, endorse or advertise any 70 | Modified Version, except to acknowledge the contribution(s) of the 71 | Copyright Holder(s) and the Author(s) or with their explicit written 72 | permission. 73 | 74 | 5) The Font Software, modified or unmodified, in part or in whole, 75 | must be distributed entirely under this license, and must not be 76 | distributed under any other license. The requirement for fonts to 77 | remain under this license does not apply to any document created 78 | using the Font Software. 79 | 80 | TERMINATION 81 | This license becomes null and void if any of the above conditions are 82 | not met. 83 | 84 | DISCLAIMER 85 | THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 86 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF 87 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 88 | OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE 89 | COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 90 | INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL 91 | DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 92 | FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM 93 | OTHER DEALINGS IN THE FONT SOFTWARE. 94 | -------------------------------------------------------------------------------- /scripts/logic_manager.gd: -------------------------------------------------------------------------------- 1 | extends Node 2 | 3 | const WIDTH : int = 6 4 | const HEIGHT : int = 12 5 | const SPAWN_ROWS : int = 6 # top 6 rows are for spawning pieces 6 | const MAX_LEVEL : int = 5 7 | const COMBO_ON_CAPTURE : bool = false # player gets to move again after a capture 8 | const COMBO_ON_BUTTON : bool = false # player gets to move again after a button press 9 | const COMBO_ON_BUTTON_AND_CAPTURE : bool = true # move again when a piece and button are captured on the same move 10 | var in_corners = [IntVec2.new(1,1), IntVec2.new(1,4), IntVec2.new(4,1), IntVec2.new(4,4)] 11 | var corners = [IntVec2.new(0,0), IntVec2.new(0,5), IntVec2.new(5,0), IntVec2.new(5,5)] 12 | var offset_corners = [IntVec2.new(0,1), IntVec2.new(1,5), IntVec2.new(5,4), IntVec2.new(4,0)] 13 | var offset_corners2 = [IntVec2.new(1,0), IntVec2.new(5,1), IntVec2.new(4,5), IntVec2.new(0,4)] 14 | var one_butt = [IntVec2.new(0,1)] 15 | var full_butt = [ 16 | IntVec2.new(0,0), IntVec2.new(0,1), IntVec2.new(0,2), IntVec2.new(0,3), IntVec2.new(0,4), IntVec2.new(0,5), 17 | IntVec2.new(1,0), IntVec2.new(1,1), IntVec2.new(1,2), IntVec2.new(1,3), IntVec2.new(1,4), IntVec2.new(1,5), 18 | IntVec2.new(2,0), IntVec2.new(2,1), IntVec2.new(2,2), IntVec2.new(2,3), IntVec2.new(2,4), IntVec2.new(2,5), 19 | IntVec2.new(3,0), IntVec2.new(3,1), IntVec2.new(3,2), IntVec2.new(3,3), IntVec2.new(3,4), IntVec2.new(3,5), 20 | IntVec2.new(4,0), IntVec2.new(4,1), IntVec2.new(4,2), IntVec2.new(4,3), IntVec2.new(4,4), IntVec2.new(4,5), 21 | IntVec2.new(5,0), IntVec2.new(5,1), IntVec2.new(5,2), IntVec2.new(5,3), IntVec2.new(5,4), IntVec2.new(5,5), 22 | ] 23 | var double_offset = [ 24 | IntVec2.new(0,1), IntVec2.new(1,5), IntVec2.new(5,4), IntVec2.new(4,0), 25 | IntVec2.new(2,1), IntVec2.new(4,2), IntVec2.new(3,4), IntVec2.new(1,3) 26 | ] 27 | var double_offset_2 = [ 28 | IntVec2.new(1,0), IntVec2.new(5,1), IntVec2.new(4,5), IntVec2.new(0,4), 29 | IntVec2.new(1,2), IntVec2.new(2,4), IntVec2.new(4,3), IntVec2.new(3,1) 30 | ] 31 | var lvl1 = [ 32 | IntVec2.new(0,2), IntVec2.new(0,3), IntVec2.new(2,0), IntVec2.new(3,0), 33 | IntVec2.new(2,5), IntVec2.new(3,5), IntVec2.new(5,2), IntVec2.new(5,3) 34 | ] 35 | var lvl2 = [ 36 | IntVec2.new(0,0), IntVec2.new(5,0), IntVec2.new(5,5), IntVec2.new(0,5), 37 | IntVec2.new(1,2), IntVec2.new(1,3), IntVec2.new(2,1), IntVec2.new(3,1), 38 | IntVec2.new(2,4), IntVec2.new(3,4), IntVec2.new(4,2), IntVec2.new(4,3) 39 | ] 40 | var lvl3 = [ 41 | IntVec2.new(0,2), IntVec2.new(1,1), IntVec2.new(1,4), IntVec2.new(2,0), 42 | IntVec2.new(2,2), IntVec2.new(2,5), IntVec2.new(3,0), IntVec2.new(3,3), 43 | IntVec2.new(3,5), IntVec2.new(4,1), IntVec2.new(4,4), IntVec2.new(5,2), 44 | IntVec2.new(0,3), IntVec2.new(5,3) 45 | ] 46 | var lvl4 = [ 47 | IntVec2.new(0,1), IntVec2.new(0,4), IntVec2.new(1,0), IntVec2.new(1,2), 48 | IntVec2.new(1,3), IntVec2.new(1,5), IntVec2.new(2,1), IntVec2.new(2,4), 49 | IntVec2.new(3,1), IntVec2.new(3,4), IntVec2.new(4,0), IntVec2.new(4,2), 50 | IntVec2.new(4,3), IntVec2.new(4,5), IntVec2.new(5,1), IntVec2.new(5,4) 51 | ] 52 | var lvl5 = [ 53 | IntVec2.new(0,0), IntVec2.new(0,2), IntVec2.new(0,3), IntVec2.new(0,5), 54 | IntVec2.new(1,1), IntVec2.new(1,4), IntVec2.new(2,0), IntVec2.new(2,2), 55 | IntVec2.new(2,3), IntVec2.new(2,5), IntVec2.new(3,0), IntVec2.new(3,2), 56 | IntVec2.new(3,3), IntVec2.new(3,5), IntVec2.new(4,1), IntVec2.new(4,4), 57 | IntVec2.new(5,0), IntVec2.new(5,2), IntVec2.new(5,3), IntVec2.new(5,5) 58 | ] 59 | var lvl6 = full_butt 60 | 61 | var button_positions = { # button positions for each level 62 | 0: lvl1, 63 | 1: lvl2, 64 | 2: lvl3, 65 | 3: lvl4, 66 | 4: lvl5, 67 | 5: lvl6 68 | } 69 | 70 | var _next_object_id : int 71 | 72 | var phase : int 73 | var level : int 74 | var turn : int 75 | var lives : int 76 | var moves : Array 77 | var next_move : int 78 | var enemy_ids : Array # list of ids 79 | var player_id : int 80 | var player : PieceLogic 81 | var pieces # dictionary whose keys are piece ids 82 | var board : Array # 2D array, with piece IDs in occupied spaces, null if empty 83 | var formation_factory : PawnFormationFactory 84 | var button_ids : Array 85 | var buttons #dictionary whose keys are button ids 86 | var button_map : Array 87 | var has_been_hit_on_this_turn : bool 88 | var piece_captured_on_this_turn : bool 89 | var button_pressed_on_this_turn : bool 90 | var combo_count : int 91 | var pos_at_level_start : IntVec2 92 | var try_player_move_has_been_called_this_turn : bool 93 | var death_count : int 94 | 95 | signal spawn_enemy(id, pos) # int and IntVec2 96 | signal move_enemy(id, new_pos) # int and IntVec2 97 | signal enemy_death(id, old_pos) # int and IntVec2 98 | signal pawn_promotion(id, pos) # int and IntVec2 99 | signal move_draw(type, slot, new_next_type) # MoveType and int and MoveType 100 | signal phase_change(new_phase) # Phases 101 | signal on_damage(id, pos, life_remaining) # int id of the enemy that attacked, IntVec2 of pos, int 102 | signal on_death() # int if of the enemy that attacked, IntVec2 of pos 103 | signal on_level_up(new_level) # int 104 | signal on_button_press(id) # int id of the button 105 | signal on_button_create(id, pos) # int id of the new button, IntVec2 of its position 106 | signal on_life_up(life_remaining) # int the new number of lives 107 | signal on_combo(pos, count) # the count is an int of the number of combos so far 108 | signal reset_buttons() 109 | 110 | # Called when the node enters the scene tree for the first time. 111 | func _ready(): 112 | randomize() 113 | 114 | # Completely reset EVERYTHING 115 | func reset(same_level: bool = false): 116 | # Variables 117 | if same_level: 118 | for i in range(0, moves.size() - lives - 1): 119 | emit_signal("on_life_up", lives + i + 1) 120 | _next_object_id = 1 121 | if phase != Phases.GAME_OVER && not same_level: # If it was a game over, then we do not reset the level 122 | level = 0 123 | death_count = 0 124 | phase = Phases.PRE_GAME 125 | turn = 0 126 | moves = [MoveType.GOOD_PAWN, MoveType.GOOD_PAWN, MoveType.GOOD_PAWN] 127 | next_move = MoveType.GOOD_PAWN 128 | lives = moves.size() 129 | enemy_ids = [] # list of ids 130 | player_id = 0 131 | combo_count = 0 132 | player = PieceLogic.new({ 133 | 'id': player_id, 134 | 'is_player': true, 135 | 'pos': IntVec2.new(2,2), 136 | 'type': MoveType.GOOD_PAWN 137 | }) 138 | if same_level: 139 | player.pos = pos_at_level_start 140 | pos_at_level_start = player.pos 141 | pieces = { # keys are piece ids 142 | player_id: player 143 | } 144 | has_been_hit_on_this_turn = false 145 | piece_captured_on_this_turn = false 146 | button_pressed_on_this_turn = false 147 | try_player_move_has_been_called_this_turn = false 148 | board = [] # 2D array, with piece IDs in occupied spaces, null if empty 149 | formation_factory = PawnFormationFactory.new(HEIGHT - SPAWN_ROWS - 1, WIDTH) 150 | 151 | # Init the moves 152 | var starting_moves = [ 153 | MoveType.KING, 154 | MoveType.QUEEN, 155 | MoveType.BISHOP, 156 | MoveType.ROOK, 157 | MoveType.KNIGHT 158 | ] 159 | for i in range(0, moves.size()): 160 | var move_idx = randi() % starting_moves.size() 161 | moves[i] = starting_moves[move_idx] 162 | starting_moves.remove(move_idx) 163 | next_move = starting_moves[randi() % starting_moves.size()] 164 | # Init the board 165 | for x in range(0, WIDTH): 166 | var column = [] 167 | for y in range(0, HEIGHT): 168 | column.push_back(null) 169 | board.push_back(column) 170 | # Add player to board 171 | board[player.pos.x][player.pos.y] = player_id 172 | 173 | init_buttons() 174 | if phase != Phases.GAME_OVER && not same_level: # If it was a game over, then we do not reset the level 175 | emit_signal("on_level_up", level) 176 | 177 | # Returns unique ids for pieces 178 | func get_next_id(): 179 | var next = _next_object_id 180 | _next_object_id = _next_object_id + 1 181 | return next 182 | 183 | func increment_phase(): 184 | if phase == Phases.GAME_OVER || phase == Phases.YOU_WIN: 185 | print("The phase is %s" % Phases.string(phase)) 186 | return 187 | 188 | if phase == Phases.PRE_GAME: 189 | phase = Phases.PLAYER_MOVE 190 | elif phase == Phases.PLAYER_MOVE: 191 | if not try_player_move_has_been_called_this_turn: 192 | return 193 | if should_level_up(): 194 | pos_at_level_start = player.pos 195 | combo_count = 0 196 | if level >= MAX_LEVEL: 197 | kill_all_enemies() 198 | print("DEATH COUNT: %s" % death_count) 199 | phase = Phases.YOU_WIN 200 | else: 201 | kill_all_enemies() 202 | level_up() 203 | elif (COMBO_ON_CAPTURE && piece_captured_on_this_turn)\ 204 | || (COMBO_ON_BUTTON && button_pressed_on_this_turn)\ 205 | || (COMBO_ON_BUTTON_AND_CAPTURE && button_pressed_on_this_turn && piece_captured_on_this_turn): 206 | combo_count = combo_count + 1 207 | emit_signal("on_combo", player.pos, combo_count) 208 | print("COMBO %s" % combo_count) 209 | phase = Phases.PLAYER_MOVE 210 | else: 211 | combo_count = 0 212 | phase = Phases.QUEEN_MOVE 213 | elif phase == Phases.QUEEN_MOVE: 214 | phase = Phases.PAWN_MOVE 215 | elif phase == Phases.PAWN_MOVE: 216 | phase = Phases.SPAWN_ENEMY 217 | elif phase == Phases.SPAWN_ENEMY: 218 | phase = Phases.PLAYER_MOVE 219 | elif phase == Phases.GAME_OVER: 220 | phase = Phases.GAME_OVER 221 | elif phase == Phases.YOU_WIN: 222 | phase = Phases.YOU_WIN 223 | emit_signal("phase_change", phase) 224 | print("The phase is %s" % Phases.string(phase)) 225 | do_phase() 226 | if phase == Phases.PLAYER_MOVE && enemy_ids.size() == 0 && turn == 0 && level == 5: 227 | spawn_boss_enemies() 228 | 229 | func do_phase(): 230 | if phase == Phases.PLAYER_MOVE: 231 | has_been_hit_on_this_turn = false 232 | piece_captured_on_this_turn = false 233 | button_pressed_on_this_turn = false 234 | try_player_move_has_been_called_this_turn = false 235 | elif phase == Phases.QUEEN_MOVE: 236 | move_queens() 237 | elif phase == Phases.PAWN_MOVE: 238 | move_pawns() 239 | elif phase == Phases.SPAWN_ENEMY: 240 | spawn_enemies() 241 | turn = turn + 1 242 | print("Turn %s" % turn) 243 | 244 | func init_buttons(): 245 | emit_signal("reset_buttons") 246 | button_map = [] 247 | for x in range(0, WIDTH): 248 | var col = [] 249 | for y in range(0, HEIGHT - SPAWN_ROWS): 250 | col.push_back(null) 251 | button_map.push_back(col) 252 | button_ids = [] 253 | buttons = {} 254 | for p in button_positions[level]: 255 | if p.equals(player.pos) && level == 5: 256 | continue 257 | var id = get_next_id() 258 | button_ids.push_back(id) 259 | buttons[id] = ButtonLogic.new({ 'id': id, 'pos': IntVec2.new(p.x, p.y) }) 260 | button_map[p.x][p.y] = id 261 | print("making a button") 262 | emit_signal("on_button_create", id, p) 263 | 264 | func should_level_up() -> bool: 265 | for id in button_ids: 266 | if not buttons[id].pressed: 267 | return false 268 | return true 269 | 270 | func level_up(): 271 | level = level +1 272 | turn = 0 273 | print("Level %s, Turn %s" % [level, turn]) 274 | emit_signal("on_level_up", level) 275 | init_buttons() 276 | while lives < moves.size(): 277 | lives = lives + 1 278 | emit_signal("on_life_up", lives) 279 | 280 | func kill_all_enemies(): 281 | var enemy_ids_copy = enemy_ids.duplicate() 282 | for id in enemy_ids_copy: 283 | print(pieces[id]) 284 | kill_enemy_piece(id) 285 | 286 | # Increments the phase and moves the player if the move is legal 287 | # Expects: 288 | # int slot which slot the player is using to move (corresponds to a piece type) 289 | # IntVec2 pos where the player wants to move 290 | # Returns: 291 | # true if the move succeeded, false otherwise 292 | func try_player_move(slot: int, pos: IntVec2) -> bool: 293 | try_player_move_has_been_called_this_turn = true 294 | var type = moves[slot] 295 | var legal_player_moves = get_legal_moves(player.pos, type, true) 296 | for legal_move in legal_player_moves: 297 | if pos.equals(legal_move): 298 | # Move the player 299 | board[player.pos.x][player.pos.y] = null 300 | player.pos.x = pos.x 301 | player.pos.y = pos.y 302 | var old_tenant = board[pos.x][pos.y] 303 | if old_tenant != null: 304 | # A piece was captured! 305 | piece_captured_on_this_turn = true 306 | kill_enemy_piece(old_tenant) 307 | if button_map[pos.x][pos.y] != null: 308 | # A button was pressed! 309 | var button_id = button_map[pos.x][pos.y] 310 | var button = buttons[button_id] 311 | if not button.pressed: 312 | button.pressed = true 313 | button_pressed_on_this_turn = true 314 | emit_signal("on_button_press", button_id) 315 | board[pos.x][pos.y] = player.id 316 | moves[slot] = next_move 317 | next_move = get_random_player_move() 318 | emit_signal("move_draw", moves[slot], slot, next_move) 319 | increment_phase() 320 | return true 321 | return false 322 | 323 | # Returns a random MoveType for the player 324 | func get_random_player_move() -> int: 325 | var bucket = [ 326 | MoveType.GOOD_PAWN, MoveType.QUEEN, 327 | MoveType.KNIGHT, MoveType.KING, 328 | MoveType.BISHOP, MoveType.ROOK, 329 | MoveType.KNIGHT, MoveType.KING, 330 | MoveType.BISHOP, MoveType.ROOK 331 | ] 332 | # Repeatedly draw from the bucket until a new move is selected, or 333 | # some maximum number of draws is reached 334 | var counter = 0 335 | var max_tries = 3 336 | var move = 0 337 | while true: 338 | counter = counter + 1 339 | move = bucket[randi() % bucket.size()] 340 | var i = moves.find(move) 341 | var already_have_it = i >= 0 && i < lives 342 | if counter >= max_tries || not already_have_it: 343 | break 344 | return move 345 | 346 | # Deletes an enemy piece from the game 347 | # Expects: 348 | # int id is the id of an enemy piece 349 | func kill_enemy_piece(id : int, emit : bool = true): 350 | var index = enemy_ids.find(id) 351 | if index != -1: 352 | enemy_ids.remove(index) 353 | var pos = pieces[id].pos 354 | board[pos.x][pos.y] = null 355 | pieces[id].is_dead = true 356 | pieces.erase(id) 357 | if emit: 358 | emit_signal("enemy_death", id, pos) 359 | 360 | # Returns an array of IntVec2, representing all legal moves. 361 | # Currently, "not moving" is always a legal move 362 | # Expects: 363 | # IntVec2 pos where you want to go 364 | # MoveType type the type of piece trying to move 365 | # bool is_player true if the piece is the player piece 366 | # Returns: 367 | # array of IntVec2 368 | func get_legal_moves(pos: IntVec2, type: int, is_player: bool) -> Array: 369 | var moves = [IntVec2.new(pos.x, pos.y)] #staying still is always legal? 370 | if type == MoveType.BAD_PAWN: 371 | var move = IntVec2.new(pos.x, pos.y - 1) 372 | if is_on_board_and_empty(move): 373 | moves.push_back(IntVec2.new(pos.x, pos.y - 1)) 374 | var attacks = [ 375 | IntVec2.new(pos.x-1, pos.y-1), IntVec2.new(pos.x+1, pos.y-1) 376 | ] 377 | for attack in attacks: 378 | if is_on_play_area_and_attackable(attack, is_player) && not is_on_play_area_and_empty(attack): 379 | moves.push_back(attack) 380 | if type == MoveType.GOOD_PAWN: 381 | var move = IntVec2.new(pos.x, pos.y + 1) 382 | if is_on_play_area_and_empty(move): 383 | moves.push_back(IntVec2.new(pos.x, pos.y + 1)) 384 | var attacks = [ 385 | IntVec2.new(pos.x-1, pos.y+1), IntVec2.new(pos.x+1, pos.y+1) 386 | ] 387 | for attack in attacks: 388 | if is_on_play_area_and_attackable(attack, is_player) && not is_on_play_area_and_empty(attack): 389 | moves.push_back(attack) 390 | if type == MoveType.KNIGHT: 391 | var potentialMoves = [ 392 | IntVec2.new(pos.x+1, pos.y+2), IntVec2.new(pos.x+2,pos.y+1), 393 | IntVec2.new(pos.x-1, pos.y+2), IntVec2.new(pos.x-2,pos.y+1), 394 | IntVec2.new(pos.x+1, pos.y-2), IntVec2.new(pos.x+2,pos.y-1), 395 | IntVec2.new(pos.x-1, pos.y-2), IntVec2.new(pos.x-2,pos.y-1), 396 | ] 397 | for move in potentialMoves: 398 | if is_on_play_area_and_attackable(move, is_player): 399 | moves.push_back(move) 400 | if type == MoveType.KING: 401 | var potentialMoves = [ 402 | IntVec2.new(pos.x, pos.y+1), IntVec2.new(pos.x+1, pos.y+1), 403 | IntVec2.new(pos.x+1, pos.y), IntVec2.new(pos.x+1, pos.y-1), 404 | IntVec2.new(pos.x, pos.y-1), IntVec2.new(pos.x-1, pos.y-1), 405 | IntVec2.new(pos.x-1, pos.y), IntVec2.new(pos.x-1, pos.y+1) 406 | ] 407 | for move in potentialMoves: 408 | if is_on_play_area_and_attackable(move, is_player): 409 | moves.push_back(move) 410 | if type == MoveType.ROOK || type == MoveType.QUEEN: 411 | var directions = [ 412 | IntVec2.new(1,0), IntVec2.new(0,1), IntVec2.new(-1,0), IntVec2.new(0,-1) 413 | ] 414 | for dir in directions: 415 | var move = IntVec2.new(pos.x, pos.y) 416 | while true: 417 | move = move.add(dir) 418 | if is_on_play_area_and_empty(move): 419 | moves.push_back(move) 420 | elif is_on_play_area_and_attackable(move, is_player): 421 | moves.push_back(move) 422 | break 423 | else: 424 | break 425 | if type == MoveType.BISHOP || type == MoveType.QUEEN: 426 | var directions = [ 427 | IntVec2.new(1,1), IntVec2.new(1,-1), IntVec2.new(-1,1),IntVec2.new(-1,-1) 428 | ] 429 | for dir in directions: 430 | var move = IntVec2.new(pos.x, pos.y) 431 | while true: 432 | move = move.add(dir) 433 | if is_on_play_area_and_empty(move): 434 | moves.push_back(move) 435 | elif is_on_play_area_and_attackable(move, is_player): 436 | moves.push_back(move) 437 | break 438 | else: 439 | break 440 | if is_player && moves.size() > 1: 441 | moves.pop_front() 442 | return moves 443 | 444 | func is_on_board_and_empty(pos: IntVec2) -> bool: 445 | return is_on_board(pos) && board[pos.x][pos.y] == null 446 | 447 | func is_on_board(pos: IntVec2) -> bool: 448 | return pos.x >= 0 && pos.y >= 0 && pos.x < WIDTH && pos.y < HEIGHT 449 | 450 | func is_on_play_area_and_empty(pos: IntVec2) -> bool: 451 | return is_on_play_area(pos) && board[pos.x][pos.y] == null 452 | 453 | # if is_player is true, then enemy squares and empty squares are attackable 454 | func is_on_play_area_and_attackable(pos: IntVec2, is_player: bool) -> bool: 455 | if is_on_play_area(pos): 456 | if board[pos.x][pos.y] == null: 457 | return true 458 | elif is_player || not has_been_hit_on_this_turn: # ensures that player can only be damaged once per turn 459 | var attacked_piece_id = board[pos.x][pos.y] 460 | var attacked_piece = pieces[attacked_piece_id] 461 | if attacked_piece.is_player != is_player: 462 | return true 463 | return false 464 | 465 | func is_on_play_area(pos: IntVec2) -> bool: 466 | return pos.x >= 0 && pos.y >= 0 && pos.x < WIDTH && pos.y < HEIGHT - SPAWN_ROWS 467 | 468 | # Adds a piece to the board at the given location. 469 | # Requires: the pos is not occupied 470 | # Inputs: 471 | # IntVec2 pos can be anywhere on the board 472 | # MoveType type 473 | # Returns: 474 | # int the piece ID 475 | func add_enemy_piece(pos: IntVec2, type: int): 476 | var id = get_next_id() 477 | enemy_ids.push_back(id) 478 | pieces[id] = PieceLogic.new({ 479 | 'id': id, 480 | 'is_player': false, 481 | 'pos': pos, 482 | 'type': type 483 | }) 484 | board[pos.x][pos.y] = id 485 | emit_signal("spawn_enemy", id, pos) 486 | 487 | class PieceSorter: 488 | static func sort_bottom_to_top(a: PieceLogic, b: PieceLogic): 489 | if a.pos.y < b.pos.y: 490 | return true 491 | elif a.pos.y == b.pos.y && a.pos.x < b.pos.x: 492 | return true 493 | return false 494 | 495 | func move_queens(): 496 | var queens = [] 497 | for id in enemy_ids: 498 | var piece = pieces[id] 499 | if piece.type == MoveType.QUEEN: 500 | queens.push_back(piece) 501 | queens.sort_custom(PieceSorter, "sort_bottom_to_top") 502 | for queen in queens: 503 | var moves = get_legal_moves(queen.pos, MoveType.QUEEN, false) 504 | var best_move = moves.pop_back() 505 | var best_proximity = no_sqrt_dist_to_player(best_move) 506 | for move in moves: 507 | if board[move.x][move.y] == player_id: 508 | best_move = move 509 | break 510 | var proximity = no_sqrt_dist_to_player(move) 511 | if proximity < best_proximity: 512 | best_move = move 513 | best_proximity = proximity 514 | move_enemy(queen, best_move) 515 | 516 | func no_sqrt_dist_to_player(pos : IntVec2): 517 | var dx = player.pos.x - pos.x 518 | var dy = player.pos.y - pos.y 519 | return dx * dx + dy * dy 520 | 521 | func move_pawns(): 522 | var pawns = [] 523 | for id in enemy_ids: 524 | var piece = pieces[id] 525 | if piece.is_player == false && piece.type == MoveType.BAD_PAWN: 526 | pawns.push_back(piece) 527 | pawns.sort_custom(PieceSorter, "sort_bottom_to_top") 528 | for pawn in pawns: 529 | var moves = get_legal_moves(pawn.pos, MoveType.BAD_PAWN, false) 530 | var best_move = moves.pop_back() 531 | for move in moves: 532 | if board[move.x][move.y] == player_id: 533 | best_move = move 534 | break 535 | elif move.y < best_move.y: 536 | best_move = move #prefer moving down to staying still 537 | move_enemy(pawn, best_move) 538 | if pawn.pos.y == 0 && not pawn.is_dead: 539 | # Promote that boiiiii! 540 | pawn.type = MoveType.QUEEN 541 | emit_signal("pawn_promotion", pawn.id, pawn.pos) 542 | 543 | # Requires that the new_pos is a valid move 544 | # Will emit move_enemy, on_damage, on_death signals as needed 545 | func move_enemy(piece: PieceLogic, new_pos: IntVec2): 546 | var starts_off_board = piece.pos.y > HEIGHT - SPAWN_ROWS 547 | board[piece.pos.x][piece.pos.y] = null 548 | var is_capture = new_pos.equals(player.pos) 549 | if starts_off_board && new_pos.y <= HEIGHT - SPAWN_ROWS: 550 | piece.pos.x = new_pos.x 551 | piece.pos.y = new_pos.y 552 | board[piece.pos.x][piece.pos.y] = piece.id 553 | emit_signal("spawn_enemy", piece.id, piece.pos) 554 | if not is_capture: 555 | piece.pos.x = new_pos.x 556 | piece.pos.y = new_pos.y 557 | board[piece.pos.x][piece.pos.y] = piece.id 558 | emit_signal("move_enemy", piece.id, piece.pos) 559 | elif lives > 1: 560 | has_been_hit_on_this_turn = true 561 | lives = lives - 1 562 | emit_signal("move_enemy", piece.id, new_pos) 563 | emit_signal("on_damage", piece.id, new_pos, lives) 564 | kill_enemy_piece(piece.id, false) 565 | else: 566 | emit_signal("move_enemy", piece.id, new_pos) 567 | has_been_hit_on_this_turn = true 568 | lives = 0 569 | emit_signal("on_damage", piece.id, new_pos, lives) 570 | emit_signal("on_death") 571 | phase = Phases.GAME_OVER 572 | death_count = death_count + 1 573 | emit_signal("phase_change", phase) 574 | 575 | func spawn_boss_enemies(): 576 | # BOSS LEVEL!!!!! 577 | print("SPAWNING BOSS!!!") 578 | for x in range(0, WIDTH): 579 | for y in range(0, HEIGHT - SPAWN_ROWS): 580 | if x == player.pos.x && y == player.pos.y: 581 | continue 582 | var pawn = PieceLogic.new({ 583 | 'id': get_next_id(), 584 | 'is_player': false, 585 | 'pos': IntVec2.new(x,y), 586 | 'type': MoveType.BAD_PAWN 587 | }) 588 | board[pawn.pos.x][pawn.pos.y] = pawn.id 589 | enemy_ids.push_back(pawn.id) 590 | pieces[pawn.id] = pawn 591 | emit_signal("spawn_enemy", pawn.id, pawn.pos) 592 | for id in enemy_ids: 593 | emit_signal("pawn_promotion", id, pieces[id].pos) 594 | 595 | func spawn_enemies(): 596 | print("Spawning enemies. Level %s, Turn %s" % [level, turn]) 597 | var positions = formation_factory.generate(level, turn) 598 | for pos in positions: 599 | if (is_on_board_and_empty(pos)): 600 | var pawn = PieceLogic.new({ 601 | 'id': get_next_id(), 602 | 'is_player': false, 603 | 'pos': pos, 604 | 'type': MoveType.BAD_PAWN 605 | }) 606 | board[pawn.pos.x][pawn.pos.y] = pawn.id 607 | enemy_ids.push_back(pawn.id) 608 | pieces[pawn.id] = pawn 609 | if pos.y <= HEIGHT - SPAWN_ROWS: 610 | emit_signal("spawn_enemy", pawn.id, pawn.pos) 611 | --------------------------------------------------------------------------------