diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/README.md" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/README.md" index d0f0b67..7e35095 100644 --- "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/README.md" +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/README.md" @@ -67,14 +67,15 @@ ##### 剑 -- 伤害:10 + sword_level * 5 -- 范围:4 + sword_level / 4 +- 伤害:10 + sword_level * 8 +- 范围:6 + sword_level / 4 - 攻击 CD:100 total, 10 + sword_level / 5 per tick +- 击退:2 + sword_level / 4 ##### 弹弓 - 伤害:8 + slingshot_level * 2 -- 子弹速度:0.5 + 0.1 * slingshot_level +- 子弹速度:0.5 + 0.2 * slingshot_level - 攻击 CD:100 total, 2 + slingshot_level / 3 * 2 per tick ### 怪物 diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/.gitignore" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/.gitignore" new file mode 100644 index 0000000..17ed8e7 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/.gitignore" @@ -0,0 +1,2 @@ +target +.mooncakes diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/LICENSE" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/LICENSE" new file mode 100644 index 0000000..d645695 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/LICENSE" @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/README.md" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/README.md" new file mode 100644 index 0000000..896a6ec --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/README.md" @@ -0,0 +1 @@ +# Lampese/汪汪立功 \ No newline at end of file diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/VERSION" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/VERSION" new file mode 100644 index 0000000..56e6e30 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/VERSION" @@ -0,0 +1 @@ +moon 0.1.20241111 (e6d64e0 2024-11-11) diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/arch-run.sh" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/arch-run.sh" new file mode 100755 index 0000000..c467c95 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/arch-run.sh" @@ -0,0 +1,2 @@ +moon build --target wasm +w4 run ./target/wasm/release/build/汪汪立功.wasm diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/moon.mod.json" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/moon.mod.json" new file mode 100644 index 0000000..9dda27b --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/moon.mod.json" @@ -0,0 +1,13 @@ +{ + "name": "Lampese/汪汪立功", + "version": "0.1.0", + "deps": { + "moonbitlang/wasm4": "0.2.2" + }, + "readme": "README.md", + "repository": "", + "license": "Apache-2.0", + "keywords": [], + "description": "", + "source": "src" +} \ No newline at end of file diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/nix-run.sh" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/nix-run.sh" new file mode 100755 index 0000000..f413bd9 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/nix-run.sh" @@ -0,0 +1,2 @@ +moon build --target wasm-gc +nix run github:szamuboy/wasm4-nix run ./target/wasm-gc/release/build/汪汪立功.wasm diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/arrow.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/arrow.mbt" new file mode 100644 index 0000000..287751a --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/arrow.mbt" @@ -0,0 +1,119 @@ +struct Arrow { + mut pos : Position + speed : Float + k : Float + damage : Int + direction : Bool + vert : Bool + belong : Bool +} + +fn Arrow::new( + pos : Position, + speed : Float, + k : Float, + damage : Int, + direction : Bool, + vert : Bool, + belong : Bool +) -> Arrow { + { pos, speed, k, damage, direction, vert, belong } +} + +fn render_arrow(arrow : Arrow) -> Unit { + set_draw_color(1, LightBrown) + set_draw_color(2, Brown) + let (x, y) = arrow.pos.to_wasm4_pos() + @wasm4.oval(x, y, 5, 5) +} + +fn generate_arrow( + from_pos : Position, + to_pos : Position, + speed : Float, + damage : Int, + belong : Bool +) -> (UInt, Arrow) { + let id = id_pool.get_id() + let is_x_pos_equal = from_pos.x == to_pos.x + ( + id, + Arrow::new( + from_pos, + speed, + if is_x_pos_equal { + 1 + } else { + (from_pos.y - to_pos.y) / (from_pos.x - to_pos.x) + }, + damage, + from_pos.x < to_pos.x, + is_x_pos_equal, + belong, + ), + ) +} + +fn update_arrow(self : Room) -> Unit { + let erase_list : Array[UInt] = [] + for id, arrow in self.arrows { + let hitbox = get_hitbox_f(arrow.pos, 2.5) + let mut flag = false + if game.current_room.arrow_walls.shape_in_box(hitbox) { + erase_list.push(id) + flag = true + } else if arrow.belong == true && + game.player.pos.get_hitbox_f(5).intersect(hitbox) { + game.player.hp -= arrow.damage + music_attack() + erase_list.push(id) + flag = true + } else if arrow.belong == false { + if game.current_room.move_hitbox().shape_in_box(hitbox) { + erase_list.push(id) + flag = true + } + for _, enemy in self.enemys { + if get_hitbox_f(enemy.pos, 5).intersect(hitbox) { + enemy.hp -= arrow.damage + music_damage() + erase_list.push(id) + flag = true + break + } + } + } + if flag.not() { + arrow.ai() + } + } + for id in erase_list { + self.arrows.remove(id) + } +} + +fn signum(f : Float) -> Int { + if f == 0 { + 0 + } else if f < 0 { + -1 + } else { + 1 + } +} + +fn ai(self : Arrow) -> Unit { + let k_signum = signum(self.k) + let direction = (if self.direction { 1.0 } else { -1.0 }).to_float() * + (if k_signum == 0 { 1 } else { k_signum.to_float() }) + self.pos = if self.vert.not() { + let k_s = self.k * self.k + let sin = (k_s / (k_s + 1)).sqrt() + let cos = if self.k == 0 { 1.0.to_float() } else { sin / self.k } + let dy = self.speed * sin * direction + let dx = self.speed * cos * direction + { x: self.pos.x + dx, y: self.pos.y + dy } + } else { + { x: self.pos.x, y: self.pos.y + self.speed * direction } + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/bar.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/bar.mbt" new file mode 100644 index 0000000..1cfa5c9 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/bar.mbt" @@ -0,0 +1,20 @@ +fn render_hp_bar(player : Player) -> Unit { + set_main_color_with_transparent(LightBrown) + let now_hp = if player.hp < 0 { 0 } else { player.hp } + let progress = now_hp.to_float() / player.hp_max.to_float() + let break_point = 8 + float_to_int(60.0.to_float() * progress) + @wasm4.rect(8, 7, 60, 7) + set_draw_color(1, Brown) + @wasm4.rect(break_point, 7, 60 - (break_point - 8), 7) +} + +fn render_cd_bar(player : Player) -> Unit { + set_main_color_with_transparent(LightBrown) + let cd = player.weapon.get_cd() + let now_cd = if cd.cd < 0 { 0 } else { cd.cd } + let progress = (cd.total - now_cd).to_float() / cd.total.to_float() + let break_point = 88 + float_to_int(42.0.to_float() * progress) + @wasm4.rect(88, 7, 42, 7) + set_draw_color(1, Brown) + @wasm4.rect(break_point, 7, 42 - (break_point - 88), 7) +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/cd.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/cd.mbt" new file mode 100644 index 0000000..47d3a6d --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/cd.mbt" @@ -0,0 +1,23 @@ +struct CD { + mut cd : Int + total : Int + decrease : Int +} + +fn CD::new(total : Int, decrease : Int) -> CD { + { cd: total, total, decrease } +} + +fn decrease(self : CD) -> Unit { + if self.cd > 0 { + self.cd -= self.decrease + } +} + +fn refersh(self : CD) -> Unit { + self.cd = self.total +} + +fn check(self : CD) -> Bool { + self.cd <= 0 +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/color.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/color.mbt" new file mode 100644 index 0000000..e76ec2e --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/color.mbt" @@ -0,0 +1,31 @@ +enum Color { + Black + Brown + LightBrown + Grey +} + +fn to_int(self : Color) -> UInt { + match self { + Black => 1 + Brown => 2 + LightBrown => 3 + Grey => 4 + } +} + +fn set_draw_color(index : UInt, color_type : Color) -> Unit { + @wasm4.set_draw_colors(index~, color_type.to_int()) +} + +fn set_main_color_with_transparent(color_type : Color) -> Unit { + @wasm4.set_draw_colors(index=1, color_type.to_int()) + @wasm4.set_draw_colors(index=2, 0) +} + +fn init_color() -> Unit { + @wasm4.set_palette(1, @wasm4.rgb(0x040404)) // Black + @wasm4.set_palette(2, @wasm4.rgb(0x7c7464)) // Brown + @wasm4.set_palette(3, @wasm4.rgb(0xf4e4bc)) // LightBrown + @wasm4.set_palette(4, @wasm4.rgb(0x34342c)) // Grey +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/column.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/column.mbt" new file mode 100644 index 0000000..7b650b1 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/column.mbt" @@ -0,0 +1,6 @@ +fn render_weapon_column() -> Unit { + set_main_color_with_transparent(LightBrown) + @wasm4.rect(1, 40, 15, 18) // patch column + sword_texture.render_texture(3, 23) + slingshot_texture.render_texture(3, 43) +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/direction.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/direction.mbt" new file mode 100644 index 0000000..29d224f --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/direction.mbt" @@ -0,0 +1,6 @@ +enum Direction { + Left + Right + Up + Down +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/end.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/end.mbt" new file mode 100644 index 0000000..53b3129 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/end.mbt" @@ -0,0 +1,7 @@ +fn render_end_ui() -> Unit { + set_main_color_with_transparent(Black) + @wasm4.rect(22, 22, 116, 116) + set_main_color_with_transparent(LightBrown) + @wasm4.text("YOU ARE DEAD", 30, 50) + @wasm4.text("Press R to restart", 10, 75) +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/enemy.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/enemy.mbt" new file mode 100644 index 0000000..d20a22a --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/enemy.mbt" @@ -0,0 +1,130 @@ +struct Enemy { + type_ : Int + id : UInt + speed : Float + mut pos : Position + mut hp : Int + hit : Int + hitcd : CD +} + +fn render_enermy(enemy : Enemy) -> Unit { + let (x, y) = enemy.pos.to_wasm4_pos() + match enemy.type_ { + 1 => mummy_texture.render_texture(x - 5, y - 5) + 2 => skeleton_texture.render_texture(x - 5, y - 5) + 3 => bug_texture.render_texture(x - 5, y - 5) + } +} + +fn update_enemy(self : Room) -> Unit { + let erase_list : Array[UInt] = [] + for id, enemy in self.enemys { + if enemy.hp <= 0 { + erase_list.push(id) + } else if enemy.type_ == 1 || enemy.type_ == 3 { + enemy.ai_mummy() + } else { + enemy.ai_skeleton() + } + } + for id in erase_list { + self.enemys.remove(id) + game.player.hp = if game.player.hp + 5 > game.player.hp_max { + game.player.hp_max + } else { + game.player.hp + 5 + } + } +} + +fn apply(self : Enemy, pos : Position) -> Unit { + let hitbox = get_hitbox_f(pos, 5) + if game.current_room.move_hitbox().shape_in_box(hitbox).not() && + game.player.pos.get_hitbox_f(5).intersect(hitbox).not() { + self.pos = pos + } +} + +fn repel(self : Enemy, direction : Direction, range : Int) -> Unit { + self.apply( + match direction { + Up => { x: self.pos.x, y: self.pos.y + range.to_float() } + Down => { x: self.pos.x, y: self.pos.y - range.to_float() } + Left => { x: self.pos.x - range.to_float(), y: self.pos.y } + Right => { x: self.pos.x + range.to_float(), y: self.pos.y } + }, + ) +} + +fn new_mummy(id : UInt, pos : Position, level : Int) -> Enemy { + { + type_: 1, + id, + pos, + hp: 50 + level * 5, + speed: 0.35, + hit: 10 + level * 2, + hitcd: CD::new(100, 3 + level / 10), + } +} + +fn new_skeleton(id : UInt, pos : Position, level : Int) -> Enemy { + { + type_: 2, + id, + pos, + hp: 40 + level * 5, + hitcd: CD::new(100, level), + speed: 0.3.to_float(), + hit: 10 + level * 2, + } +} + +fn go(self : Enemy) -> Unit { + let way = self.pos.find_way(game.player.pos, self.speed) + self.apply({ x: way.x, y: self.pos.y }) + self.apply({ x: self.pos.x, y: way.y }) +} + +fn ai_skeleton(self : Enemy) -> Unit { + let distance = self.pos.distance(game.player.pos) + self.hitcd.decrease() + if distance > 40 { + self.go() + } else if self.hitcd.check() { + let (id, arrow) = generate_arrow( + self.pos, + game.player.pos, + self.speed, + self.hit, + true, + ) + game.current_room.arrows.set(id, arrow) + self.hitcd.refersh() + } +} + +pub fn ai_mummy(self : Enemy) -> Unit { + let distance = self.pos.distance(game.player.pos) + self.hitcd.decrease() + if distance > 11 { + self.go() + } else if self.hitcd.check() { + game.player.hp -= self.hit + music_attack() + self.hitcd.refersh() + } +} + +fn new_bug(id : UInt, pos : Position, level : Int) -> Enemy { + { + type_: 3, + id, + pos, + hp: 20 + level * 2, + speed: 0.4.to_float() + 0.05.to_float() * level.to_float(), + hit: 3 + level, + hitcd: CD::new(100, 2 + level / 10), + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/game.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/game.mbt" new file mode 100644 index 0000000..666f41a --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/game.mbt" @@ -0,0 +1,70 @@ +struct Game { + mut level : Int + mut stop : Bool + mut pause_cd : CD + player : Player + mut current_room : Room +} + +fn Game::new() -> Game { + { + level: 1, + stop: false, + pause_cd: CD::new(100, 100), + player: Player::new({ x: 80, y: 120 }), + current_room: generate_room(1), + } +} + +fn update_level(self : Player) -> Unit { + match check_next_room(self) { + Some(direction) => { + game.level += 1 + match direction { + Up => { + if game.current_room.upgrade { + self.level += 1 + self.hp += 50 + } + self.pos = { x: 73, y: 121 } + } + Down => { + if game.current_room.upgrade { + self.hp = self.hp_max + } + self.pos = { x: 31, y: 77 } + } + Left => { + if game.current_room.upgrade { + self.sword = Sword::new(self.sword.level + 1) + } + self.pos = { x: 76, y: 30 } + } + Right => { + if game.current_room.upgrade { + self.slingshot = Slingshot::new(self.slingshot.level + 1) + } + self.pos = { x: 126, y: 73 } + } + } + game.current_room = generate_room(game.level) + game.pause_cd = CD::new(50 + game.level * 2, 1) + } + None => () + } +} + +fn check_next_room(self : Player) -> Direction? { + let (x, y) = self.pos.to_wasm4_pos() + if x > 0 && x < 160 && y > 0 && y < 160 { + None + } else if x <= 0 { + Some(Left) + } else if x >= 160 { + Some(Right) + } else if y <= 0 { + Some(Up) + } else { + Some(Down) + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/hitbox.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/hitbox.mbt" new file mode 100644 index 0000000..23db03e --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/hitbox.mbt" @@ -0,0 +1,56 @@ +enum Shape { + Rect(Float, Float, Float, Float) +} + +struct HitBox { + shapes : Array[Shape] +} + +fn HitBox::new() -> HitBox { + { shapes: [] } +} + +fn add(self : HitBox, shape : Shape) -> Unit { + self.shapes.push(shape) +} + +fn merge(self : HitBox, other : HitBox) -> HitBox { + { shapes: self.shapes + other.shapes } +} + +fn intersect(self : Shape, other : Shape) -> Bool { + let Rect(x1, y1, x2, y2) = self + let Rect(x3, y3, x4, y4) = other + (x1 > x4 || x3 > x2 || y1 > y4 || y3 > y2).not() +} + +fn init_wall() -> HitBox { + let hitbox : HitBox = HitBox::new() + hitbox.add(Rect(3, 3, 70, 20)) + hitbox.add(Rect(3, 3, 20, 71)) + hitbox.add(Rect(3, 85, 20, 154)) + hitbox.add(Rect(3, 137, 71, 154)) + hitbox.add(Rect(85, 137, 154, 154)) + hitbox.add(Rect(137, 85, 154, 154)) + hitbox.add(Rect(84, 3, 154, 20)) + hitbox.add(Rect(137, 3, 154, 71)) + hitbox +} + +fn frame() -> HitBox { + let hitbox : HitBox = HitBox::new() + hitbox.add(Rect(3, 71, 20, 85)) + hitbox.add(Rect(70, 3, 84, 20)) + hitbox.add(Rect(137, 71, 154, 85)) + hitbox.add(Rect(72, 138, 86, 155)) + hitbox +} + +fn shape_in_box(self : HitBox, shape : Shape) -> Bool { + for current_shape in self.shapes { + if intersect(current_shape, shape) { + return true + } + } + false +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/id_pool.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/id_pool.mbt" new file mode 100644 index 0000000..c413b93 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/id_pool.mbt" @@ -0,0 +1,14 @@ +struct ID_Pool { + mut count : UInt +} + +fn ID_Pool::new() -> ID_Pool { + { count: 0 } +} + +fn get_id(self : ID_Pool) -> UInt { + self.count += 1 + self.count +} + +let id_pool : ID_Pool = ID_Pool::new() diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/info.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/info.mbt" new file mode 100644 index 0000000..084077f --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/info.mbt" @@ -0,0 +1,10 @@ +fn render_info(self : Player) -> Unit { + set_main_color_with_transparent(LightBrown) + @wasm4.text(if self.weapon_type == true { "1" } else { "2" }, 135, 7) + @wasm4.text( + "\{self.level}/\{self.sword.level}/\{self.slingshot.level}", + 16, + 146, + ) + @wasm4.text("\{self.hp}/\{self.hp_max}", 97, 146) +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/inputer.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/inputer.mbt" new file mode 100644 index 0000000..e76dcb6 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/inputer.mbt" @@ -0,0 +1,21 @@ +fn inputer(player : Player) -> Unit { + let gamepad = @wasm4.get_gamepad() + let mouse = @wasm4.get_mouse() + if gamepad.button_up { + player.move_(Up) + } + if gamepad.button_down { + player.move_(Down) + } + if gamepad.button_left { + player.move_(Left) + } + if gamepad.button_right { + player.move_(Right) + } + if mouse.left && player.weapon.get_cd().check() { + player.weapon.attack(player.pos, game.current_room, mouse.x, mouse.y) + } else if mouse.right && player.switch_cd.check() { + player.switch_weapon() + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/main.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/main.mbt" new file mode 100644 index 0000000..4d1415d --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/main.mbt" @@ -0,0 +1,24 @@ +let game : Game = Game::new() + +pub fn start() -> Unit { + init_color() +} + +pub fn update() -> Unit { + render(game.current_room, game.player) + if game.stop { + render_end_ui() + } else { + update_level(game.player) + update_room(game.current_room) + update_player(game.player) + if game.pause_cd.check() { + update_enemy(game.current_room) + } else { + game.pause_cd.decrease() + } + update_weapon(game.player) + update_arrow(game.current_room) + inputer(game.player) + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/moon.pkg.json" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/moon.pkg.json" new file mode 100644 index 0000000..d02c494 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/moon.pkg.json" @@ -0,0 +1,20 @@ +{ + "import": ["moonbitlang/wasm4"], + "link": { + "wasm-gc": { + "exports": ["start", "update"], + "import-memory": { + "module": "env", + "name": "memory" + } + }, + "wasm": { + "exports": ["start", "update"], + "import-memory": { + "module": "env", + "name": "memory" + }, + "heap-start-address": 6560 + } + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/music.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/music.mbt" new file mode 100644 index 0000000..4fc2371 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/music.mbt" @@ -0,0 +1,17 @@ +pub fn music_damage() -> Unit { + @wasm4.tone_note_mode( + (@wasm4.Note::new(55, bend=10), None), + @wasm4.ADSR::new(15), + @wasm4.ADSRVolume::new(50), + @wasm4.ToneFlag::new(), + ) +} + +pub fn music_attack() -> Unit { + @wasm4.tone_note_mode( + (@wasm4.Note::new(40, bend=5), None), + @wasm4.ADSR::new(15), + @wasm4.ADSRVolume::new(50), + @wasm4.ToneFlag::new(), + ) +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/obstacle.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/obstacle.mbt" new file mode 100644 index 0000000..ca29b3a --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/obstacle.mbt" @@ -0,0 +1,20 @@ +enum Obstacle { + Jar(Int, Int) + Tombstone(Int, Int) +} + +fn get_obstacle_hitbox(self : Obstacle) -> Shape { + match self { + Jar(x, y) => + Rect(x.to_float(), y.to_float(), x.to_float() + 12, y.to_float() + 12) + Tombstone(x, y) => + Rect(x.to_float(), y.to_float(), x.to_float() + 7, y.to_float() + 13) + } +} + +fn render_obstacle(self : Obstacle) -> Unit { + match self { + Jar(x, y) => jar_texture.render_texture(x, y) + Tombstone(x, y) => tombstone_texture.render_texture(x, y) + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/player.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/player.mbt" new file mode 100644 index 0000000..0c58e48 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/player.mbt" @@ -0,0 +1,65 @@ +struct Player { + mut level : Int + mut pos : Position + mut hp : Int + mut hp_max : Int + mut sword : Sword + mut slingshot : Slingshot + mut weapon : Weapon + mut weapon_type : Bool + switch_cd : CD +} + +fn Player::new(pos : Position) -> Player { + { + level: 1, + pos, + hp: 100, + hp_max: 100, + sword: Sword::new(1), + slingshot: Slingshot::new(1), + weapon: Sword(Sword::new(1)), + weapon_type: true, + switch_cd: CD::new(100, 10), + } +} + +// -------------- MOVE -------------- + +fn apply(self : Player, pos : Position) -> Unit { + let hitbox = pos.get_hitbox_f(5) + if game.current_room.move_hitbox().shape_in_box(hitbox).not() { + self.pos = pos + } +} + +fn move_(self : Player, direction : Direction) -> Unit { + match direction { + Up => self.apply({ x: self.pos.x, y: self.pos.y - 1 }) + Down => self.apply({ x: self.pos.x, y: self.pos.y + 1 }) + Left => self.apply({ x: self.pos.x - 1, y: self.pos.y }) + Right => self.apply({ x: self.pos.x + 1, y: self.pos.y }) + } +} + +// -------------- RENDER -------------- + +fn render_player(player : Player) -> Unit { + player_texture.render_texture( + float_to_int(player.pos.x - 5), + float_to_int(player.pos.y - 5), + ) +} + +// -------------- UPDATE -------------- + +fn update_player(self : Player) -> Unit { + if self.hp < 0 { + game.stop = true + } +} + +fn level_up(self : Player) -> Unit { + self.level += 1 + self.hp_max = 100 + self.level * 50 +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/pos.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/pos.mbt" new file mode 100644 index 0000000..976a65c --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/pos.mbt" @@ -0,0 +1,26 @@ +extern "wasm" fn float_to_int(f : Float) -> Int = + #| (func (param f32) (result i32) local.get 0 i32.trunc_f32_s) + +struct Position { + x : Float + y : Float +} + +fn to_wasm4_pos(self : Position) -> (Int, Int) { + (float_to_int(self.x), float_to_int(self.y)) +} + +fn distance(self : Position, other : Position) -> Float { + ((self.x - other.x) * (self.x - other.x) + + (self.y - other.y) * (self.y - other.y)).sqrt() +} + +fn get_hitbox_f(self : Position, f : Float) -> Shape { + Rect(self.x - f, self.y - f, self.x + f, self.y + f) +} + +fn find_way(self : Position, to : Position, speed : Float) -> Position { + let x_diff = speed * (to.x - self.x).compare(0).to_float() + let y_diff = speed * (to.y - self.y).compare(0).to_float() + { x: self.x + x_diff, y: self.y + y_diff } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/render.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/render.mbt" new file mode 100644 index 0000000..dfd6f68 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/render.mbt" @@ -0,0 +1,54 @@ +fn render(room : Room, player : Player) -> Unit { + render_background_normal() + if room.upgrade { + set_main_color_with_transparent(LightBrown) + render_upgrade_room() + } else if room.start { + set_main_color_with_transparent(LightBrown) + render_start_room() + } + render_weapon_column() + render_player(player) + render_hp_bar(player) + render_cd_bar(player) + render_info(player) + for obstacle in room.obstacles { + obstacle.render_obstacle() + } + for _, enemy in room.enemys { + render_enermy(enemy) + } + for _, arrow in room.arrows { + render_arrow(arrow) + } +} + +fn render_upgrade_room() -> Unit { + @wasm4.text("Upgrade Room", 35, 50) + @wasm4.text("Player", 60, 25) + @wasm4.text("HP MAX", 60, 126) + @wasm4.text("Sword", 15, 75) + @wasm4.text("Slingshot", 85, 75) +} + +fn render_start_room() -> Unit { + @wasm4.text("SOUL", 62, 40) + @wasm4.text("OF", 70, 50) + @wasm4.text("THE", 65, 60) + @wasm4.text("DESERT", 55, 70) + @wasm4.text("MOUSE 1 ATTACK", 25, 90) + @wasm4.text("MOUSE 2 SWITCH", 25, 105) +} + +fn render_background_normal() -> Unit { + render_background() + set_main_color_with_transparent(Black) +} + +fn render_background() -> Unit { + set_draw_color(1, LightBrown) + set_draw_color(2, Brown) + set_draw_color(3, Grey) + set_draw_color(4, Black) + map_texture.render_texture(0, 0) +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/room.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/room.mbt" new file mode 100644 index 0000000..10c0e17 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/room.mbt" @@ -0,0 +1,131 @@ +struct Room { + mut stop : Bool + enemys : Map[UInt, Enemy] + arrows : Map[UInt, Arrow] + walls : HitBox + arrow_walls : HitBox + mut frame : HitBox + mut obstacles : FixedArray[Obstacle] + upgrade : Bool + start : Bool +} + +fn Room::new(upgrade : Bool, start : Bool) -> Room { + { + stop: false, + walls: init_wall(), + enemys: {}, + arrows: {}, + arrow_walls: init_wall(), + frame: HitBox::new(), + obstacles: [], + upgrade, + start, + } +} + +fn update_room(self : Room) -> Unit { + if self.stop.not() { + set_main_color_with_transparent(LightBrown) + @wasm4.rect(72, 138, 15, 18) + @wasm4.rect(71, 4, 15, 18) + @wasm4.rect(4, 72, 18, 15) + @wasm4.rect(138, 72, 18, 15) + self.frame = frame() + } else { + self.frame = HitBox::new() + } + if self.enemys.is_empty() { + self.stop = true + } +} + +fn move_hitbox(self : Room) -> HitBox { + self.walls.merge(self.frame) +} + +fn arrow_hitbox(self : Room) -> HitBox { + self.walls.merge(self.frame) +} + +fn bind_style(self : Room, style : RoomStyle) -> Unit { + guard let RoomStyle(obstacles) = style + self.obstacles = obstacles + for obstacle in obstacles { + self.walls.add(obstacle.get_obstacle_hitbox()) + } +} + +fn add_enemy(self : Room, enemy : Enemy) -> Unit { + self.enemys.set(enemy.id, enemy) +} + +enum RoomStyle { + RoomStyle(FixedArray[Obstacle]) +} + +let room_styles : FixedArray[RoomStyle] = [ + RoomStyle([Jar(24, 24), Jar(24, 124), Jar(124, 124), Jar(124, 24)]), + RoomStyle( + [Jar(24, 24), Jar(24, 124), Jar(124, 124), Jar(124, 24), Tombstone(72, 72)], + ), + RoomStyle( + [Jar(24, 24), Jar(24, 124), Jar(124, 124), Jar(124, 24), Tombstone(72, 72)], + ), + RoomStyle( + [ + Tombstone(24, 24), + Tombstone(24, 121), + Tombstone(121, 121), + Tombstone(121, 24), + ], + ), + RoomStyle( + [ + Tombstone(24, 24), + Tombstone(24, 121), + Tombstone(121, 121), + Tombstone(121, 24), + Jar(75, 75), + ], + ), + RoomStyle([Jar(75, 75)]), + RoomStyle([Tombstone(72, 72)]), +] + +let room_style_upper_index : Int = room_styles.length() - 1 + +fn generate_room(level : Int) -> Room { + if level == 1 { + Room::new(false, true) + } else if level % 3 == 0 { + Room::new(true, false) + } else { + let room = Room::new(false, false) + room.bind_style(room_styles[random.next(0, room_style_upper_index)]) + let enemy_count = 3 + level / 3 + level / 10 + level / 20 + level / 40 + let enemy_level = 1 + level / 10 + level / 15 + level / 20 + let mummy_count = random.next(0, enemy_count) + let skeleton_count = random.next(0, enemy_count - mummy_count) + let bug_count = enemy_count - mummy_count - skeleton_count + for i = 1; i <= mummy_count; i = i + 1 { + let id = id_pool.get_id() + let pos = random.next_pos() + let mummy = new_mummy(id, pos, enemy_level) + room.add_enemy(mummy) + } + for i = 1; i <= skeleton_count; i = i + 1 { + let id = id_pool.get_id() + let pos = random.next_pos() + let skeleton = new_skeleton(id, pos, enemy_level) + room.add_enemy(skeleton) + } + for i = 1; i <= bug_count; i = i + 1 { + let id = id_pool.get_id() + let pos = random.next_pos() + let bug = new_bug(id, pos, enemy_level) + room.add_enemy(bug) + } + room + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/texture.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/texture.mbt" new file mode 100644 index 0000000..6a8c4e3 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/texture.mbt" @@ -0,0 +1,503 @@ +enum Texture { + Texture( + FixedArray[(Int, Int, Int, Int)], + FixedArray[(Int, Int, Int, Int)], + FixedArray[(Int, Int, Int, Int)], + FixedArray[(Int, Int, Int, Int)] + ) +} + +fn render_rect(rect : (Int, Int, Int, Int), x : Int, y : Int) -> Unit { + let (x1, y1, x2, y2) = rect + @wasm4.rect(x + x1 - 1, y + y1 - 1, x2 - x1 + 1, y2 - y1 + 1) +} + +fn render_texture(self : Texture, x : Int, y : Int) -> Unit { + guard let Texture(black, brown, light_brown, gery) = self + set_main_color_with_transparent(Black) + for rect in black { + render_rect(rect, x, y) + } + set_draw_color(1, Brown) + for rect in brown { + render_rect(rect, x, y) + } + set_draw_color(1, LightBrown) + for rect in light_brown { + render_rect(rect, x, y) + } + set_draw_color(1, Grey) + for rect in gery { + render_rect(rect, x, y) + } +} + +let map_texture : Texture = Texture( + [(1, 1, 160, 160)], + [ + (5, 5, 6, 73), + (5, 5, 73, 6), + (18, 18, 21, 21), + (29, 18, 42, 21), + (18, 29, 21, 43), + (50, 18, 64, 21), + (18, 51, 21, 65), + (187, 5, 156, 6), + (156, 7, 155, 73), + (95, 18, 110, 21), + (118, 18, 132, 21), + (140, 18, 143, 21), + (140, 29, 143, 44), + (140, 52, 143, 66), + (155, 87, 156, 156), + (5, 87, 6, 156), + (7, 155, 73, 156), + (140, 95, 143, 110), + (140, 118, 143, 132), + (87, 155, 154, 156), + (5, 155, 73, 156), + (140, 140, 143, 143), + (119, 140, 132, 143), + (95, 140, 111, 143), + (155, 5, 156, 73), + (87, 5, 154, 6), + (51, 140, 65, 143), + (29, 140, 43, 143), + (18, 140, 21, 143), + (18, 117, 21, 132), + (18, 95, 21, 109), + ], + [ + (7, 73, 22, 73), + (73, 7, 73, 22), + (22, 22, 72, 22), + (22, 22, 22, 72), + (17, 17, 72, 17), + (17, 17, 17, 72), + (3, 22, 16, 38), + (3, 42, 16, 58), + (87, 7, 87, 22), + (87, 17, 144, 17), + (87, 22, 139, 22), + (139, 22, 139, 73), + (144, 17, 144, 73), + (139, 73, 154, 73), + (7, 87, 22, 87), + (139, 87, 154, 87), + (87, 139, 87, 154), + (73, 139, 73, 154), + (139, 87, 139, 139), + (144, 87, 144, 144), + (87, 139, 139, 139), + (87, 144, 144, 144), + (22, 139, 73, 139), + (17, 144, 73, 144), + (17, 87, 17, 144), + (22, 87, 22, 139), + ], + [], +) + +let player_texture : Texture = Texture( + [ + (2, 4, 2, 7), + (3, 4, 4, 4), + (4, 5, 4, 5), + (6, 4, 7, 4), + (7, 5, 7, 5), + (11, 4, 11, 6), + (10, 7, 10, 7), + (2, 9, 2, 10), + (11, 9, 11, 10), + (3, 10, 4, 10), + (6, 10, 7, 10), + (9, 10, 10, 10), + (4, 11, 9, 11), + ], + [(5, 9, 8, 9)], + [ + (2, 1, 4, 1), + (6, 1, 6, 1), + (7, 1, 10, 2), + (1, 2, 3, 2), + (5, 2, 5, 2), + (5, 4, 5, 4), + (8, 4, 8, 5), + (10, 5, 10, 6), + (3, 5, 3, 5), + (5, 5, 6, 5), + (3, 6, 9, 7), + (3, 9, 3, 9), + (5, 10, 5, 10), + (8, 10, 8, 10), + (10, 9, 10, 9), + ], + [ + (5, 1, 5, 1), + (4, 2, 4, 2), + (6, 2, 6, 2), + (1, 3, 10, 3), + (9, 4, 9, 5), + (10, 4, 10, 4), + (3, 8, 10, 8), + (4, 9, 4, 9), + (9, 9, 9, 9), + ], +) + +let jar_texture : Texture = Texture( + [ + (4, 1, 4, 1), + (10, 1, 10, 1), + (5, 2, 5, 3), + (9, 2, 9, 3), + (3, 4, 4, 4), + (10, 4, 11, 4), + (2, 5, 2, 6), + (12, 5, 12, 6), + (1, 7, 1, 8), + (13, 7, 13, 8), + (2, 9, 2, 10), + (12, 9, 12, 10), + (3, 11, 3, 11), + (11, 11, 11, 11), + (4, 12, 4, 12), + (10, 12, 10, 12), + (5, 13, 9, 13), + ], + [ + (6, 2, 8, 2), + (7, 3, 8, 3), + (8, 4, 9, 4), + (9, 5, 11, 5), + (10, 6, 11, 6), + (10, 7, 10, 7), + (9, 8, 10, 8), + (9, 9, 9, 9), + (3, 10, 3, 10), + (8, 10, 8, 10), + (4, 11, 7, 11), + ], + [ + (5, 1, 9, 1), + (6, 3, 6, 3), + (5, 4, 7, 4), + (3, 5, 8, 9), + (2, 7, 2, 8), + (9, 6, 9, 7), + (4, 10, 7, 10), + ], + [ + (5, 12, 9, 12), + (8, 11, 10, 11), + (9, 10, 11, 10), + (10, 9, 11, 9), + (11, 7, 12, 8), + ], +) + +let skeleton_texture : Texture = Texture( + [ + (3, 1, 9, 1), + (2, 2, 2, 3), + (10, 2, 10, 2), + (1, 3, 1, 7), + (3, 4, 4, 5), + (7, 4, 8, 5), + (11, 3, 11, 7), + (5, 6, 6, 6), + (4, 7, 7, 7), + (2, 7, 2, 10), + (3, 8, 10, 8), + (10, 7, 10, 7), + (4, 9, 4, 11), + (9, 9, 9, 10), + (3, 10, 3, 10), + (11, 9, 11, 9), + (10, 10, 11, 10), + (5, 11, 9, 11), + ], + [ + (5, 2, 9, 2), + (3, 3, 4, 3), + (10, 5, 10, 5), + (9, 4, 9, 4), + (8, 3, 8, 3), + (3, 9, 3, 9), + (10, 9, 10, 9), + ], + [ + (3, 2, 4, 2), + (5, 3, 6, 5), + (7, 3, 8, 3), + (9, 3, 10, 4), + (2, 4, 2, 5), + (9, 5, 9, 5), + (2, 6, 4, 6), + (7, 6, 8, 6), + (10, 6, 10, 6), + (3, 7, 3, 7), + (9, 7, 9, 7), + (6, 9, 8, 9), + (8, 10, 8, 10), + ], + [], +) + +let tombstone_texture : Texture = Texture( + [ + (2, 1, 8, 1), + (2, 2, 2, 4), + (8, 2, 8, 4), + (1, 3, 1, 9), + (9, 3, 9, 9), + (2, 10, 2, 11), + (8, 10, 8, 11), + (3, 12, 3, 13), + (7, 12, 7, 13), + (8, 14, 8, 15), + (2, 14, 2, 15), + ], + [ + (3, 2, 7, 2), + (3, 3, 3, 3), + (7, 3, 7, 3), + (4, 4, 4, 5), + (6, 4, 6, 5), + (3, 7, 3, 8), + (7, 7, 7, 8), + (4, 9, 6, 9), + (5, 10, 5, 10), + (5, 13, 5, 13), + ], + [ + (4, 3, 6, 3), + (5, 4, 5, 5), + (2, 5, 2, 9), + (8, 5, 8, 9), + (4, 7, 4, 8), + (6, 7, 6, 8), + (3, 9, 3, 11), + (7, 9, 7, 11), + (5, 8, 5, 8), + (5, 11, 5, 12), + (3, 15, 7, 15), + ], + [ + (3, 4, 3, 5), + (7, 4, 7, 5), + (3, 6, 7, 6), + (5, 7, 5, 7), + (4, 10, 4, 13), + (6, 10, 6, 13), + (3, 12, 7, 12), + ], +) + +let slingshot_texture : Texture = Texture( + [ + (8, 1, 9, 1), + (7, 2, 8, 2), + (7, 3, 7, 3), + (6, 3, 6, 4), + (5, 5, 5, 5), + (4, 6, 4, 9), + (4, 10, 8, 10), + (3, 11, 3, 11), + (1, 12, 2, 12), + (9, 9, 9, 9), + (9, 7, 9, 7), + (10, 8, 10, 8), + (10, 6, 10, 6), + (11, 5, 11, 7), + ], + [(9, 2, 9, 6), (10, 7, 10, 7), (11, 8, 11, 8)], + [], + [ + (7, 1, 7, 1), + (6, 2, 6, 2), + (5, 3, 5, 3), + (4, 4, 5, 4), + (4, 5, 4, 5), + (3, 5, 3, 10), + (2, 10, 2, 10), + (1, 11, 2, 11), + (5, 8, 5, 8), + (5, 9, 8, 9), + (8, 8, 9, 8), + ], +) + +let bug_texture : Texture = Texture( + [ + (7, 1, 10, 1), + (4, 2, 6, 2), + (11, 2, 11, 2), + (3, 3, 3, 3), + (2, 4, 5, 4), + (9, 4, 9, 8), + (1, 5, 1, 5), + (2, 6, 2, 6), + (4, 6, 4, 6), + (6, 5, 6, 5), + (7, 5, 7, 8), + (10, 6, 11, 6), + (1, 7, 1, 9), + (3, 8, 4, 9), + (6, 7, 6, 9), + (11, 8, 11, 8), + (8, 9, 8, 9), + (2, 10, 2, 10), + (5, 10, 5, 10), + ], + [ + (9, 3, 10, 3), + (6, 4, 7, 4), + (10, 4, 10, 5), + (11, 5, 11, 5), + (8, 5, 8, 6), + (5, 6, 5, 8), + (6, 6, 6, 6), + (4, 7, 4, 7), + (2, 8, 2, 8), + ], + [ + (7, 2, 10, 2), + (4, 3, 8, 3), + (11, 3, 11, 4), + (8, 4, 8, 4), + (2, 5, 5, 5), + (1, 6, 1, 6), + (3, 6, 3, 7), + (2, 7, 2, 7), + (11, 7, 11, 7), + (8, 8, 8, 8), + (2, 9, 2, 9), + (5, 9, 5, 9), + ], + [], +) + +let sword_texture : Texture = Texture( + [ + (11, 1, 13, 1), + (13, 2, 13, 3), + (4, 5, 5, 5), + (5, 6, 5, 6), + (2, 9, 2, 10), + (3, 9, 3, 9), + (8, 9, 8, 10), + (9, 10, 9, 10), + (1, 11, 1, 13), + (5, 11, 5, 11), + (4, 12, 5, 12), + (7, 12, 7, 12), + (2, 13, 3, 13), + ], + [ + (2, 11, 3, 12), + (4, 10, 4, 10), + (5, 9, 5, 9), + (6, 8, 6, 8), + (7, 7, 7, 7), + (8, 6, 8, 6), + (9, 5, 9, 5), + (10, 4, 10, 4), + (11, 3, 11, 3), + (4, 7, 4, 8), + (6, 10, 7, 10), + (8, 11, 8, 11), + (3, 6, 3, 6), + ], + [ + (6, 7, 6, 7), + (7, 6, 7, 6), + (8, 5, 8, 5), + (9, 4, 9, 4), + (10, 3, 10, 3), + (7, 8, 7, 8), + (8, 7, 8, 7), + (9, 6, 9, 6), + (10, 5, 10, 5), + (11, 4, 11, 4), + ], + [ + (2, 5, 2, 6), + (3, 5, 3, 5), + (4, 6, 4, 6), + (3, 7, 3, 8), + (5, 7, 5, 8), + (3, 10, 3, 10), + (4, 11, 4, 11), + (5, 10, 5, 10), + (4, 9, 4, 9), + (6, 9, 7, 9), + (6, 11, 7, 11), + (8, 12, 8, 12), + (9, 11, 9, 12), + (6, 6, 6, 6), + (7, 5, 7, 5), + (8, 4, 8, 4), + (9, 3, 9, 3), + (10, 2, 11, 2), + (12, 2, 12, 4), + (8, 8, 8, 8), + (9, 7, 9, 7), + (10, 6, 10, 6), + (11, 5, 11, 5), + ], +) + +let mummy_texture : Texture = Texture( + [ + (2, 2, 2, 6), + (3, 1, 3, 1), + (9, 1, 9, 1), + (10, 2, 10, 6), + (4, 4, 4, 4), + (7, 4, 7, 4), + (3, 6, 3, 7), + (4, 7, 4, 7), + (5, 5, 6, 7), + (7, 7, 9, 7), + (9, 6, 9, 6), + (1, 8, 2, 8), + (4, 8, 4, 9), + (8, 8, 8, 9), + (10, 8, 11, 8), + (1, 9, 1, 10), + (2, 10, 2, 10), + (3, 9, 3, 10), + (5, 10, 6, 10), + (11, 9, 11, 9), + (9, 9, 9, 10), + (10, 10, 11, 10), + (3, 11, 9, 11), + ], + [ + (4, 1, 8, 1), + (4, 3, 4, 3), + (7, 3, 7, 3), + (3, 5, 4, 5), + (8, 5, 8, 6), + (9, 5, 9, 5), + (4, 6, 4, 6), + (6, 9, 7, 9), + (4, 10, 4, 10), + (7, 10, 8, 10), + ], + [ + (3, 2, 9, 2), + (3, 3, 3, 4), + (5, 3, 6, 4), + (8, 3, 9, 4), + (7, 5, 7, 6), + (3, 8, 3, 8), + (2, 9, 2, 9), + (5, 8, 5, 9), + (6, 8, 7, 8), + (9, 8, 9, 8), + (10, 9, 10, 9), + ], + [], +) diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/weapon.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/weapon.mbt" new file mode 100644 index 0000000..96a4509 --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/weapon.mbt" @@ -0,0 +1,156 @@ +enum Weapon { + Sword(Sword) + Slingshot(Slingshot) +} + +fn switch_weapon(self : Player) -> Unit { + if self.weapon_type == true { + self.weapon = Slingshot(self.slingshot) + self.weapon_type = false + } else { + self.weapon = Sword(self.sword) + self.weapon_type = true + } + self.switch_cd.refersh() +} + +fn attack( + self : Weapon, + pos : Position, + room : Room, + mouse_x : Int, + mouse_y : Int +) -> Unit { + match self { + Sword(sword) => sword.sword_attack(pos, room, mouse_x, mouse_y) + Slingshot(slingshot) => + slingshot.slingshot_attack(pos, room, mouse_x, mouse_y) + } +} + +fn get_cd(self : Weapon) -> CD { + match self { + Sword(sword) => sword.cd + Slingshot(slingshot) => slingshot.cd + } +} + +fn update_weapon(self : Player) -> Unit { + self.switch_cd.decrease() + match self.weapon { + Sword(sword) => sword.cd.decrease() + Slingshot(slingshot) => slingshot.cd.decrease() + } +} + +struct Sword { + level : Int + damage : Int + range : Int + cd : CD + repel : Int +} + +fn Sword::new(level : Int) -> Sword { + { + level, + damage: 10 + level * 8, + range: 6 + level / 4, + cd: CD::new(100, 10 + level / 5), + repel: 2 + level / 4, + } +} + +fn sword_determine_direction( + mouse_x : Int, + mouse_y : Int, + pos : Position +) -> Direction { + let dx = mouse_x.to_float() - pos.x + let dy = mouse_y.to_float() - pos.y + if dy < 0 && dx.abs() < dy.abs() { + Up + } else if dy > 0 && dx.abs() < dy.abs() { + Down + } else if dx < 0 && dy.abs() < dx.abs() { + Left + } else { + Right + } +} + +fn sword_generate_attack_hitbox( + self : Direction, + sword : Sword, + pos : Position +) -> Shape { + let range = sword.range.to_float() + match self { + Left => Rect(pos.x - 5 - range, pos.y - 5, pos.x - 5, pos.y) + Right => Rect(pos.x, pos.y - 5, pos.x + 5 + range, pos.y + 5) + Up => Rect(pos.x - 5, pos.y - 5 - range, pos.x + 5, pos.y) + Down => Rect(pos.x - 5, pos.y, pos.x + 5, pos.y + 5 + range) + } +} + +fn sword_attack( + self : Sword, + pos : Position, + room : Room, + mouse_x : Int, + mouse_y : Int +) -> Unit { + for _, enemy in room.enemys { + let { damage, .. } = self + let direction = sword_determine_direction(mouse_x, mouse_y, pos) + let hitbox = direction.sword_generate_attack_hitbox(self, pos) + if hitbox.intersect(get_hitbox_f(enemy.pos, 5)) { + enemy.hp -= damage + music_damage() + enemy.repel(direction, self.repel) + } + } + self.cd.refersh() +} + +struct Slingshot { + level : Int + damage : Int + speed : Float + cd : CD +} + +fn Slingshot::new(level : Int) -> Slingshot { + { + level, + damage: 8 + level * 2, + speed: 0.5.to_float() + 0.2.to_float() * level.to_float(), + cd: CD::new(100, 2 + level / 3 * 2), + } +} + +fn slingshot_attack( + self : Slingshot, + pos : Position, + room : Room, + mouse_x : Int, + mouse_y : Int +) -> Unit { + let (id, arrow) = generate_arrow( + pos, + { x: mouse_x.to_float(), y: mouse_y.to_float() }, + self.speed, + self.damage, + false, + ) + room.arrows.set(id, arrow) + self.cd.refersh() +} + +fn refersh_weapon(self : Player) -> Unit { + self.weapon = if self.weapon_type { + Sword(self.sword) + } else { + Slingshot(self.slingshot) + } +} diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/xor_shift.mbt" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/xor_shift.mbt" new file mode 100644 index 0000000..c4a136e --- /dev/null +++ "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/code/src/xor_shift.mbt" @@ -0,0 +1,20 @@ +struct RandomGenerator { + mut seed : Int +} + +fn RandomGenerator::new(seed : Int) -> RandomGenerator { + { seed, } +} + +fn next(self : RandomGenerator, range_l : Int, range_r : Int) -> Int { + self.seed = self.seed ^ (self.seed << 13) + self.seed = self.seed ^ (self.seed >> 17) + self.seed = self.seed ^ (self.seed << 5) + range_l + self.seed.abs() % (range_r - range_l + 1) +} + +fn next_pos(self : RandomGenerator) -> Position { + { x: self.next(40, 100).to_float(), y: self.next(40, 100).to_float() } +} + +let random : RandomGenerator = RandomGenerator::new(114514) diff --git "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/game.wasm" "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/game.wasm" index aadbafc..59a715b 100644 Binary files "a/teams/\346\261\252\346\261\252\347\253\213\345\212\237/game.wasm" and "b/teams/\346\261\252\346\261\252\347\253\213\345\212\237/game.wasm" differ