diff --git a/.gitignore b/.gitignore index 259148f..7e23f45 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,8 @@ *.exe *.out *.app +*.elf +*.sav +*.gba + +.vscode/* \ No newline at end of file diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..07875b6 --- /dev/null +++ b/Makefile @@ -0,0 +1,58 @@ +#--------------------------------------------------------------------------------------------------------------------- +# TARGET is the name of the output. +# BUILD is the directory where object files & intermediate files will be placed. +# LIBBUTANO is the main directory of butano library (https://github.com/GValiente/butano). +# PYTHON is the path to the python interpreter. +# SOURCES is a list of directories containing source code. +# INCLUDES is a list of directories containing extra header files. +# DATA is a list of directories containing binary data. +# GRAPHICS is a list of directories containing files to be processed by grit. +# AUDIO is a list of directories containing files to be processed by mmutil. +# DMGAUDIO is a list of directories containing files to be processed by mod2gbt and s3m2gbt. +# ROMTITLE is a uppercase ASCII, max 12 characters text string containing the output ROM title. +# ROMCODE is a uppercase ASCII, max 4 characters text string containing the output ROM code. +# USERFLAGS is a list of additional compiler flags: +# Pass -flto to enable link-time optimization. +# Pass -O0 to improve debugging. +# USERASFLAGS is a list of additional assembler flags. +# USERLDFLAGS is a list of additional linker flags: +# Pass -flto=auto -save-temps to enable parallel link-time optimization. +# USERLIBDIRS is a list of additional directories containing libraries. +# Each libraries directory must contains include and lib subdirectories. +# USERLIBS is a list of additional libraries to link with the project. +# USERBUILD is a list of additional directories to remove when cleaning the project. +# EXTTOOL is an optional command executed before processing audio, graphics and code files. +# +# All directories are specified relative to the project directory where the makefile is found. +#--------------------------------------------------------------------------------------------------------------------- +TARGET := $(notdir $(CURDIR)) +BUILD := build +LIBBUTANO := ../../butano +PYTHON := python +SOURCES := src ../../common/src +INCLUDES := include ../../common/include +DATA := +GRAPHICS := graphics ../../common/graphics +AUDIO := audio ../../common/audio +DMGAUDIO := dmg_audio ../../common/dmg_audio +ROMTITLE := ROCK_PAPER_SHOTGUN +ROMCODE := SBTP +USERFLAGS := +USERASFLAGS := +USERLDFLAGS := +USERLIBDIRS := +USERLIBS := +USERBUILD := +EXTTOOL := + +#--------------------------------------------------------------------------------------------------------------------- +# Export absolute butano path: +#--------------------------------------------------------------------------------------------------------------------- +ifndef LIBBUTANOABS + export LIBBUTANOABS := $(realpath $(LIBBUTANO)) +endif + +#--------------------------------------------------------------------------------------------------------------------- +# Include main makefile: +#--------------------------------------------------------------------------------------------------------------------- +include $(LIBBUTANOABS)/butano.mak diff --git a/audio/.gitignore b/audio/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/dmg_audio/.gitignore b/dmg_audio/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/graphics/assault_class_.bmp b/graphics/assault_class_.bmp new file mode 100644 index 0000000..fbb7b4d Binary files /dev/null and b/graphics/assault_class_.bmp differ diff --git a/graphics/assault_class_.json b/graphics/assault_class_.json new file mode 100644 index 0000000..d831df0 --- /dev/null +++ b/graphics/assault_class_.json @@ -0,0 +1,4 @@ +{ + "type": "sprite", + "height": 16 +} diff --git a/graphics/board.bmp b/graphics/board.bmp new file mode 100644 index 0000000..a44711d Binary files /dev/null and b/graphics/board.bmp differ diff --git a/graphics/board.json b/graphics/board.json new file mode 100644 index 0000000..8c2602a --- /dev/null +++ b/graphics/board.json @@ -0,0 +1,3 @@ +{ + "type": "regular_bg" +} \ No newline at end of file diff --git a/graphics/d_red.bmp b/graphics/d_red.bmp new file mode 100644 index 0000000..6503ec3 Binary files /dev/null and b/graphics/d_red.bmp differ diff --git a/graphics/d_red.json b/graphics/d_red.json new file mode 100644 index 0000000..df4ccdd --- /dev/null +++ b/graphics/d_red.json @@ -0,0 +1,4 @@ +{ + "type": "sprite", + "height": 16 +} \ No newline at end of file diff --git a/graphics/dst_cursor.bmp b/graphics/dst_cursor.bmp new file mode 100644 index 0000000..8ecdcd2 Binary files /dev/null and b/graphics/dst_cursor.bmp differ diff --git a/graphics/dst_cursor.json b/graphics/dst_cursor.json new file mode 100644 index 0000000..d831df0 --- /dev/null +++ b/graphics/dst_cursor.json @@ -0,0 +1,4 @@ +{ + "type": "sprite", + "height": 16 +} diff --git a/graphics/g_arrow.bmp b/graphics/g_arrow.bmp new file mode 100644 index 0000000..21ef8e1 Binary files /dev/null and b/graphics/g_arrow.bmp differ diff --git a/graphics/g_arrow.json b/graphics/g_arrow.json new file mode 100644 index 0000000..df4ccdd --- /dev/null +++ b/graphics/g_arrow.json @@ -0,0 +1,4 @@ +{ + "type": "sprite", + "height": 16 +} \ No newline at end of file diff --git a/graphics/selection_cursor.bmp b/graphics/selection_cursor.bmp new file mode 100644 index 0000000..afafbe3 Binary files /dev/null and b/graphics/selection_cursor.bmp differ diff --git a/graphics/selection_cursor.json b/graphics/selection_cursor.json new file mode 100644 index 0000000..d831df0 --- /dev/null +++ b/graphics/selection_cursor.json @@ -0,0 +1,4 @@ +{ + "type": "sprite", + "height": 16 +} diff --git a/graphics/tiles.bmp b/graphics/tiles.bmp new file mode 100644 index 0000000..2d76613 Binary files /dev/null and b/graphics/tiles.bmp differ diff --git a/graphics/tiles.json b/graphics/tiles.json new file mode 100644 index 0000000..df4ccdd --- /dev/null +++ b/graphics/tiles.json @@ -0,0 +1,4 @@ +{ + "type": "sprite", + "height": 16 +} \ No newline at end of file diff --git a/graphics/wasp.bmp b/graphics/wasp.bmp new file mode 100644 index 0000000..8d96afd Binary files /dev/null and b/graphics/wasp.bmp differ diff --git a/graphics/wasp.json b/graphics/wasp.json new file mode 100644 index 0000000..daf7360 --- /dev/null +++ b/graphics/wasp.json @@ -0,0 +1,4 @@ +{ + "type": "sprite", + "height": 16 +} \ No newline at end of file diff --git a/img/pathfinding-0.png b/img/pathfinding-0.png new file mode 100644 index 0000000..1ff0617 Binary files /dev/null and b/img/pathfinding-0.png differ diff --git a/img/pathfinding-1.png b/img/pathfinding-1.png new file mode 100644 index 0000000..dfc26ee Binary files /dev/null and b/img/pathfinding-1.png differ diff --git a/img/pathfinding-2.png b/img/pathfinding-2.png new file mode 100644 index 0000000..9da28df Binary files /dev/null and b/img/pathfinding-2.png differ diff --git a/include/.gitignore b/include/.gitignore new file mode 100644 index 0000000..e69de29 diff --git a/include/pathfinder.h b/include/pathfinder.h new file mode 100644 index 0000000..ef7ed3d --- /dev/null +++ b/include/pathfinder.h @@ -0,0 +1,30 @@ +#ifndef PATHFINDER_H +#define PATHFINDER_H + +#include "queue.h" +#include "stack.h" +#include "bn_log.h" + +#define ROW 9 +#define COL 9 + +class Pathfinder +{ + public: + Pathfinder(); + void reset(); + bool is_valid(int row, int col); + bool found; + int game[ROW][COL] = {0}; + void search(int row, int col); + void add_obstacle(int row, int col); + bool check_obstacle(int row, int col); + private: + Queue queue_r {}; + Queue queue_c {}; + Queue queue_count {}; + bool visited[ROW*COL] = {false}; + bool obstacles[ROW*COL] = {false}; +}; + +#endif \ No newline at end of file diff --git a/include/queue.h b/include/queue.h new file mode 100644 index 0000000..da47b60 --- /dev/null +++ b/include/queue.h @@ -0,0 +1,76 @@ +#ifndef QUEUE_H +#define QUEUE_H + +template +class Queue +{ + public: + bool empty(); + bool is_full(); + T front(); + T rear(); + void push(T element); + void pop(); + void clear(); + private: + T _queue[1000]; + int _capacity = 1000; + int _size = 0; + int _front = 0; + int _rear = _capacity - 1; +}; + +template +void Queue::clear() +{ + _size = _front = 0; + _rear = _capacity - 1; +} + +template +bool Queue::empty() +{ + return _size == 0; +} + +template +bool Queue::is_full() +{ + return _capacity == _size; +} + +template +T Queue::front() +{ + return _queue[_front]; +} + +template +T Queue::rear() +{ + return _rear; +} + +template +void Queue::push(T element) +{ + if(!is_full()) + { + _rear = (_rear + 1) % _capacity; + _queue[_rear] = element; + _size++; + } +} + +template +void Queue::pop() +{ + if(!empty()) + { + _front = (_front + 1) % _capacity; + _size--; + } +} + + +#endif \ No newline at end of file diff --git a/include/scene.h b/include/scene.h new file mode 100644 index 0000000..922087b --- /dev/null +++ b/include/scene.h @@ -0,0 +1,18 @@ +#ifndef SCENE_H +#define SCENE_H + +enum SceneType +{ + MENU, + LVL1 +}; + +class Scene +{ + public: + virtual void init() = 0; + virtual void update() = 0; + virtual ~Scene() = 0; +}; + +#endif \ No newline at end of file diff --git a/include/stack.h b/include/stack.h new file mode 100644 index 0000000..0f4dae9 --- /dev/null +++ b/include/stack.h @@ -0,0 +1,57 @@ +#ifndef STACK_H +#define STACK_H + +template +class Stack +{ + public: + void push(T element); + void pop(T& element); + bool empty(); + bool is_full(); + void clear(); + private: + T _stack[1000]; + int _top = -1; + int capacity = 1000; +}; + +template +void Stack::push(T element) +{ + if(!is_full()) + { + _top++; + _stack[_top] = element; + } +} + +template +void Stack::pop(T& element) +{ + if(!empty()) + { + element = _stack[_top]; + _top--; + } +} + +template +bool Stack::empty() +{ + return _top == -1; +} + +template +bool Stack::is_full() +{ + return _top == capacity; +} + +template +void Stack::clear() +{ + _top = -1; +} + +#endif \ No newline at end of file diff --git a/include/tiles.h b/include/tiles.h new file mode 100644 index 0000000..7038c69 --- /dev/null +++ b/include/tiles.h @@ -0,0 +1,12 @@ +#ifndef TILES_H +#define TILES_H + +#include "bn_sprite_ptr.h" +#include "bn_sprite_items_tiles.h" + +struct Tile +{ + bn::sprite_ptr tile = bn::sprite_items::tiles.create_sprite(0, 0); +}; + +#endif \ No newline at end of file diff --git a/include/turn_controller.h b/include/turn_controller.h new file mode 100644 index 0000000..e0c643d --- /dev/null +++ b/include/turn_controller.h @@ -0,0 +1,19 @@ +#ifndef TURN_CONTROLLER_H +#define TURN_CONTROLLER_H + +class TurnController +{ + public: + TurnController(); + TurnController(int player_u, int npc_u, int total_player_u, int total_npc_u); + bool is_player_turn = false; + int turn_timer = 20; + private: + int player_units; + int npc_units; + int total_player_units; + int total_npc_units; +}; + + +#endif \ No newline at end of file diff --git a/include/unit.h b/include/unit.h new file mode 100644 index 0000000..9318ecf --- /dev/null +++ b/include/unit.h @@ -0,0 +1,26 @@ +#ifndef UNIT_H +#define UNIT_H + +enum UnitType { Player, NPC}; + +class Unit +{ + public: + Unit(int r, int c, int X, int Y, UnitType unit_type_); + Unit(); + + int row; + int col; + + int x; + int y; + + int movement_counter; + int movement_radius; + bool is_moving; + + UnitType unit_type; +}; + + +#endif \ No newline at end of file diff --git a/include/util.h b/include/util.h new file mode 100644 index 0000000..900850e --- /dev/null +++ b/include/util.h @@ -0,0 +1,26 @@ +#ifndef UTIL_H +#define UTIL_H + +#include "bn_sprite_ptr.h" + +#include "unit.h" +#include "pathfinder.h" +#include "turn_controller.h" + +namespace Util +{ + void move_unit(Unit& curr_unit, bn::sprite_ptr& curr_sprite, Pathfinder& pf, int& movement_counter); + void vaild_moves(Pathfinder& pf, int row, int col, int count); + void paint_moves_1(Unit& curr_unit,Pathfinder& pf, bn::sprite_ptr& v_tile_1, bn::sprite_ptr& v_tile_2, + bn::sprite_ptr& v_tile_3, bn::sprite_ptr& v_tile_4); + void paint_moves_2(Unit& curr_unit,Pathfinder& pf, bn::sprite_ptr& v_tile_5, bn::sprite_ptr& v_tile_6, + bn::sprite_ptr& v_tile_7, bn::sprite_ptr& v_tile_8); + void paint_moves_3(Unit& curr_unit,Pathfinder& pf, bn::sprite_ptr& v_tile_9, bn::sprite_ptr& v_tile_10, + bn::sprite_ptr& v_tile_11, bn::sprite_ptr& v_tile_12); + void hide_tiles(bn::sprite_ptr& v_tile_1, bn::sprite_ptr& v_tile_2, + bn::sprite_ptr& v_tile_3, bn::sprite_ptr& v_tile_4, bn::sprite_ptr& v_tile_5, bn::sprite_ptr& v_tile_6, + bn::sprite_ptr& v_tile_7, bn::sprite_ptr& v_tile_8, bn::sprite_ptr& v_tile_9, bn::sprite_ptr& v_tile_10, + bn::sprite_ptr& v_tile_11, bn::sprite_ptr& v_tile_12); +}; + +#endif \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..84479c3 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,362 @@ +#include "bn_core.h" +#include "bn_math.h" +#include "bn_keypad.h" +#include "bn_display.h" +#include "bn_blending.h" +#include "bn_bg_palettes.h" +#include "bn_regular_bg_ptr.h" +#include "bn_sprites_mosaic.h" +#include "bn_sprite_actions.h" +#include "bn_sprite_builder.h" +#include "bn_sprite_text_generator.h" +#include "bn_sprite_animate_actions.h" +#include "bn_sprite_first_attributes.h" +#include "bn_sprite_third_attributes.h" +#include "bn_sprite_position_hbe_ptr.h" +#include "bn_sprite_first_attributes_hbe_ptr.h" +#include "bn_sprite_third_attributes_hbe_ptr.h" +#include "bn_sprite_affine_second_attributes.h" +#include "bn_sprite_regular_second_attributes.h" +#include "bn_sprite_affine_second_attributes_hbe_ptr.h" +#include "bn_sprite_regular_second_attributes_hbe_ptr.h" +#include "bn_log.h" + +#include "bn_sprite_items_tiles.h" +#include "bn_sprite_items_assault_class_.h" +#include "bn_sprite_items_selection_cursor.h" +#include "bn_sprite_items_dst_cursor.h" +#include "bn_sprite_items_g_arrow.h" +#include "bn_sprite_items_wasp.h" +#include "bn_regular_bg_items_board.h" + +#include "common_info.h" +#include "common_variable_8x16_sprite_font.h" + +#include "scene.h" +#include "util.h" +#include "unit.h" +#include "tiles.h" +#include "queue.h" +#include "pathfinder.h" +#include "turn_controller.h" + + +int main() +{ + bn::core::init(); + + bn::sprite_text_generator text_generator(common::variable_8x16_sprite_font); + text_generator.set_alignment(bn::sprite_text_generator::alignment_type::LEFT); + + bn::vector text_sprites; + + bn::bg_palettes::set_transparent_color(bn::color(16, 16, 16)); + + bn::string_view debug_text[2]; + debug_text[0] = "Player turn"; + text_generator.generate(45, 70, debug_text[0], text_sprites); + + bn::regular_bg_ptr board_bg = bn::regular_bg_items::board.create_bg(0, 0); + + int movement_counter = 0; + const int origin_r = 0; + const int origin_c = 0; + const int origin_pos_x = -104; + const int origin_pos_y = -73; + + int wasp_r = 5; + int wasp_c = 8; + int wasp_pos_x = origin_pos_x + (16 * wasp_c); + int wasp_pos_y = origin_pos_y + (16 * wasp_r); + + bn::sprite_ptr red_tile = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 1); + + bn::sprite_ptr sp_2 = bn::sprite_items::assault_class_.create_sprite(origin_pos_x, origin_pos_y); + + bn::sprite_ptr sp_wasp = bn::sprite_items::wasp.create_sprite(wasp_pos_x, wasp_pos_y); + + bn::sprite_animate_action<8> sp_wasp_animate_action = bn::create_sprite_animate_action_forever( + sp_wasp, 12, bn::sprite_items::wasp.tiles_item(), 0, 1, 2, 3, 4, 5, 6, 7); + + bn::sprite_animate_action<4> sp_2_animate_action = bn::create_sprite_animate_action_forever( + sp_2, 12, bn::sprite_items::assault_class_.tiles_item(), 0, 1, 2, 3); + + Unit player_unit(origin_r, origin_c, origin_pos_x, origin_pos_y, UnitType::Player); + player_unit.movement_counter = 100; //debug + Unit *curr_unit = &player_unit; + + Unit wasp_unit(wasp_r, wasp_c, wasp_pos_x, wasp_pos_y, UnitType::NPC); + wasp_unit.movement_counter = 3; + + bn::sprite_ptr curr_sp = sp_2; + + + bn::sprite_ptr v_tile_1 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_2 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_3 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_4 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + v_tile_1.set_visible(false); + v_tile_2.set_visible(false); + v_tile_3.set_visible(false); + v_tile_4.set_visible(false); + + bn::sprite_ptr v_tile_5 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_6 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_7 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_8 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + + v_tile_5.set_visible(false); + v_tile_6.set_visible(false); + v_tile_7.set_visible(false); + v_tile_8.set_visible(false); + + bn::sprite_ptr v_tile_9 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_10 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_11 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + bn::sprite_ptr v_tile_12 = bn::sprite_items::dst_cursor.create_sprite(origin_pos_x, origin_pos_y, 2); + + v_tile_9.set_visible(false); + v_tile_10.set_visible(false); + v_tile_11.set_visible(false); + v_tile_12.set_visible(false); + + int cursor_pos_x = origin_pos_x; + int cursor_pos_y = origin_pos_y; + int cursor_r = 0; + int cursor_c = 0; + bn::sprite_ptr sp_cursor = bn::sprite_items::selection_cursor.create_sprite(cursor_pos_x, cursor_pos_y); + bn::sprite_ptr sp_cursor_blocked = bn::sprite_items::selection_cursor.create_sprite(cursor_pos_x, cursor_pos_y, 2); + sp_cursor_blocked.set_visible(false); + + //UI + int sp_arrow_x = 45; int sp_arrow_y = -20; + bn::sprite_ptr sp_arrow = bn::sprite_items::g_arrow.create_sprite(sp_arrow_x, sp_arrow_y); + sp_arrow.set_visible(false); + bn::sprite_text_generator ui_text_generator(common::variable_8x16_sprite_font); + ui_text_generator.set_alignment(bn::sprite_text_generator::alignment_type::LEFT); + + bn::vector ui_text_1_sp; + bn::vector ui_text_2_sp; + bn::vector ui_text_3_sp; + bn::vector ui_text_4_sp; + bn::string_view ui_text[4]; + + bn::bg_palettes::set_transparent_color(bn::color(16, 16, 16)); + + ui_text[0] = "Move"; + ui_text[1] = "Attack"; + ui_text[2] = "End Turn"; + ui_text[3] = "Back"; + + + Pathfinder pf; + + int dst_r = -1; + int dst_c = -1; + + + red_tile.set_position(origin_pos_x + (dst_r * 16) , origin_pos_y + ((dst_c - 1) * 16)); + + pf.add_obstacle(0, 4); + pf.add_obstacle(1, 1); + pf.add_obstacle(2, 1); + pf.add_obstacle(6, 5); + pf.add_obstacle(8, 5); + pf.add_obstacle(8, 6); + pf.add_obstacle(8, 7); + pf.add_obstacle(8, 8); + + + TurnController tc; + tc.is_player_turn = true; + + bool is_menu = false; + bool prepare_menu = false; + + while(true) + { + bn::core::update(); + //keypad controls + if(!is_menu) + { + if(bn::keypad::pressed(bn::keypad::key_type::LEFT) && pf.is_valid(cursor_r, cursor_c - 1) && !pf.check_obstacle(cursor_r, cursor_c - 1)) + { + cursor_pos_x -= 16; + cursor_c--; + } + else if(bn::keypad::pressed(bn::keypad::key_type::RIGHT) && pf.is_valid(cursor_r, cursor_c + 1) && !pf.check_obstacle(cursor_r, cursor_c + 1)) + { + cursor_pos_x += 16; + cursor_c++; + } + else if(bn::keypad::pressed(bn::keypad::key_type::DOWN) && pf.is_valid(cursor_r + 1, cursor_c) && !pf.check_obstacle(cursor_r + 1, cursor_c)) + { + cursor_pos_y += 16; + cursor_r++; + } + else if(bn::keypad::pressed(bn::keypad::key_type::UP) && pf.is_valid(cursor_r - 1, cursor_c) && !pf.check_obstacle(cursor_r - 1, cursor_c)) + { + cursor_pos_y -= 16; + cursor_r--; + } + } + else + { + if(bn::keypad::pressed(bn::keypad::key_type::DOWN)) + { + sp_arrow_y += 20; + if(sp_arrow_y >= 40) + sp_arrow_y = 40; + } + else if(bn::keypad::pressed(bn::keypad::key_type::UP)) + { + sp_arrow_y -= 20; + if(sp_arrow_y <= -20) + sp_arrow_y = -20; + } + } + + if(bn::keypad::pressed(bn::keypad::key_type::B) && is_menu) + { + sp_arrow.set_visible(false); + is_menu = false; + } + + if(prepare_menu) + { + ui_text_1_sp.clear(); + ui_text_2_sp.clear(); + ui_text_3_sp.clear(); + ui_text_4_sp.clear(); + ui_text_generator.generate(60, -20, ui_text[0], ui_text_1_sp); + ui_text_generator.generate(60, 0, ui_text[1], ui_text_2_sp); + ui_text_generator.generate(60, 20, ui_text[2], ui_text_3_sp); + ui_text_generator.generate(60, 40, ui_text[3], ui_text_4_sp); + prepare_menu = false; + } + + if(!is_menu && !prepare_menu) + { + ui_text_1_sp.clear(); + ui_text_2_sp.clear(); + ui_text_3_sp.clear(); + ui_text_4_sp.clear(); + + Util::hide_tiles(v_tile_1, v_tile_2, v_tile_3, v_tile_4, v_tile_5, v_tile_6, v_tile_7, v_tile_8, v_tile_9, v_tile_10, v_tile_11, v_tile_12); + } + + if(bn::keypad::pressed(bn::keypad::key_type::A) && tc.is_player_turn && !is_menu) + { + //if cursor on unit + //then show available path + //else + if(cursor_r == curr_unit->row && cursor_c == curr_unit->col) + { + + sp_arrow.set_visible(true); + is_menu = true; + prepare_menu = true; + + //get movement radius + BN_LOG("Movement radius"); + Util::vaild_moves(pf, curr_unit->row, curr_unit->col, curr_unit->movement_radius); + Util::paint_moves_1(*curr_unit, pf, v_tile_1, v_tile_2, v_tile_3, v_tile_4); + Util::paint_moves_2(*curr_unit, pf, v_tile_5, v_tile_6, v_tile_7, v_tile_8); + Util::paint_moves_3(*curr_unit, pf, v_tile_9, v_tile_10, v_tile_11, v_tile_12); + pf.reset(); + } + else + { + Util::hide_tiles(v_tile_1, v_tile_2, v_tile_3, v_tile_4, v_tile_5, v_tile_6, v_tile_7, v_tile_8, v_tile_9, v_tile_10, v_tile_11, v_tile_12); + + sp_arrow.set_visible(false); + + dst_r = cursor_r; + dst_c = cursor_c; + BN_LOG(dst_r, " , ", dst_c); + BN_LOG(curr_unit->row, " , ", curr_unit->col); + pf.search(dst_r, dst_c); + for(int i =0;irow != dst_r || curr_unit->col != dst_c)) + { + + Util::move_unit(*curr_unit, curr_sp, pf, movement_counter); + } + else if((curr_unit->row == dst_r) && (curr_unit->col == dst_c)) + { + if(tc.is_player_turn) + { + dst_r = dst_c = -1; + red_tile.set_position(origin_pos_x + (dst_c * 16) , origin_pos_y + (dst_r * 16)); // hide tile + BN_LOG("CPU turn"); + debug_text[0] = "CPU turn"; + text_sprites.clear(); + text_generator.generate(45, 70, debug_text[0], text_sprites); + sp_cursor_blocked.set_visible(true); + sp_cursor.set_visible(false); + pf.reset(); + //after player's turn + //transfer control to CPU + tc.is_player_turn = false; + tc.turn_timer = 100; + dst_r = player_unit.row; + dst_c = player_unit.col; + curr_unit = &wasp_unit; + wasp_unit.movement_counter = 3; + curr_sp = sp_wasp; + BN_LOG(dst_r, " , ", dst_c); + BN_LOG(curr_unit->row, " , ", curr_unit->col); + pf.search(dst_r, dst_c); + } + else + { + BN_LOG("player turn"); + debug_text[0] = "Player turn"; + text_sprites.clear(); + text_generator.generate(45, 70, debug_text[0], text_sprites); + sp_cursor.set_visible(true); + sp_cursor_blocked.set_visible(false); + dst_r = dst_c = -1; + pf.reset(); + tc.is_player_turn = true; + curr_unit = &player_unit; + player_unit.movement_counter = 100; //debug + curr_sp = sp_2; + } + } + + if(curr_unit->movement_counter == 0 || (!tc.is_player_turn && tc.turn_timer <= 0)) + { + BN_LOG("player turn"); + debug_text[0] = "Player turn"; + text_sprites.clear(); + text_generator.generate(45, 70, debug_text[0], text_sprites); + sp_cursor.set_visible(true); + sp_cursor_blocked.set_visible(false); + dst_r = dst_c = -1; + pf.reset(); + tc.is_player_turn = true; + curr_unit = &player_unit; + player_unit.movement_counter = 100; //debug + curr_sp = sp_2; + } + + sp_2_animate_action.update(); + sp_wasp_animate_action.update(); + sp_cursor.set_position(cursor_pos_x, cursor_pos_y); + sp_cursor_blocked.set_position(cursor_pos_x, cursor_pos_y); + sp_arrow.set_position(sp_arrow_x, sp_arrow_y); + } + return 0; +} diff --git a/src/pathfinder.cpp b/src/pathfinder.cpp new file mode 100644 index 0000000..321148f --- /dev/null +++ b/src/pathfinder.cpp @@ -0,0 +1,83 @@ +#include "pathfinder.h" + +Pathfinder::Pathfinder() +{ + reset(); +} + +void Pathfinder::reset() +{ + found = false; + for(int i=0;i= 0 && row < ROW) && (col >= 0 && col < COL)); +} + +void Pathfinder::add_obstacle(int row, int col) +{ + obstacles[ROW* row + col] = true; +} + +bool Pathfinder::check_obstacle(int row, int col) +{ + return obstacles[ROW * row + col]; +} + +void Pathfinder::search(int row, int col) +{ + reset(); + int count = 1; + queue_r.push(row); queue_c.push(col); + queue_count.push(count); + visited[ROW * row + col] = true; + + while(!queue_r.empty()) + { + int rr = queue_r.front(); queue_r.pop(); + int cc = queue_c.front(); queue_c.pop(); + + count = queue_count.front(); queue_count.pop(); + game[rr][cc] = count; + + //SOUTH + if(is_valid(rr+1, cc) && !visited[ROW * (rr+1) + cc] && !obstacles[ROW * (rr+1) + cc]) + { + queue_r.push(rr+1); queue_c.push(cc); queue_count.push(count + 1); + visited[ROW * (rr+1) + cc] = true; + } + //NORTH + if(is_valid(rr-1, cc) && !visited[ROW * (rr-1) + cc] && !obstacles[ROW * (rr-1) + cc]) + { + queue_r.push(rr-1); queue_c.push(cc); queue_count.push(count + 1); + visited[ROW * (rr-1) + cc] = true; + } + //EAST + if(is_valid(rr, cc+1) && !visited[ROW * rr + (cc+1)] && !obstacles[ROW * rr + (cc+1)]) + { + queue_r.push(rr); queue_c.push(cc+1); queue_count.push(count + 1); + visited[ROW * rr + (cc+1)] = true; + } + //WEST + if(is_valid(rr, cc-1) && !visited[ROW * rr + (cc-1)] && !obstacles[ROW * rr + (cc-1)]) + { + queue_r.push(rr); queue_c.push(cc-1); queue_count.push(count + 1); + visited[ROW * rr + (cc-1)] = true; + } + } +} \ No newline at end of file diff --git a/src/scene.cpp b/src/scene.cpp new file mode 100644 index 0000000..df68dfb --- /dev/null +++ b/src/scene.cpp @@ -0,0 +1,6 @@ +#include "scene.h" + +Scene::~Scene() +{ + +} \ No newline at end of file diff --git a/src/turn_controller.cpp b/src/turn_controller.cpp new file mode 100644 index 0000000..22a434d --- /dev/null +++ b/src/turn_controller.cpp @@ -0,0 +1,15 @@ +#include "turn_controller.h" + +TurnController::TurnController() +{ + TurnController(1, 1, 1, 1); +} + +TurnController::TurnController(int player_u, int npc_u, int total_player_u, int total_npc_u) +{ + player_units = player_u; + npc_units = npc_u; + total_player_units = total_player_u; + total_npc_units = total_npc_u; + is_player_turn = true; +} \ No newline at end of file diff --git a/src/unit.cpp b/src/unit.cpp new file mode 100644 index 0000000..b79978b --- /dev/null +++ b/src/unit.cpp @@ -0,0 +1,19 @@ +#include "unit.h" + +Unit::Unit(int r, int c, int X, int Y, UnitType unit_type_) +{ + row = r; + col = c; + x = X; + y = Y; + movement_counter = 0; + movement_radius = 3;//default + is_moving = false; + unit_type = unit_type_; +} + +Unit::Unit() +{ + Unit(0, 0, 0, 0, NPC); +} + diff --git a/src/util.cpp b/src/util.cpp new file mode 100644 index 0000000..62e877f --- /dev/null +++ b/src/util.cpp @@ -0,0 +1,168 @@ +#include "util.h" + +void Util::move_unit(Unit &curr_unit, bn::sprite_ptr& curr_sprite, Pathfinder& pf, int& movement_counter) +{ + if(movement_counter == 30 && curr_unit.movement_counter > 0) + { + // BN_LOG("moving"); + + if(pf.is_valid(curr_unit.row + 1, curr_unit.col) && pf.game[curr_unit.row + 1][curr_unit.col] == pf.game[curr_unit.row][curr_unit.col] - 1) + { + BN_LOG("SOUTH"); + + curr_unit.row = curr_unit.row + 1; + curr_unit.y = curr_unit.y + 16; + curr_sprite.set_y(curr_unit.y); + curr_unit.movement_counter--; + } + else if(pf.is_valid(curr_unit.row, curr_unit.col + 1) && pf.game[curr_unit.row][curr_unit.col + 1] == pf.game[curr_unit.row][curr_unit.col] - 1) + { + BN_LOG("EAST"); + + curr_unit.col = curr_unit.col + 1; + curr_unit.x = curr_unit.x + 16; + curr_sprite.set_x(curr_unit.x); + curr_sprite.set_horizontal_flip(false); + curr_unit.movement_counter--; + } + else if(pf.is_valid(curr_unit.row - 1, curr_unit.col) && pf.game[curr_unit.row - 1][curr_unit.col] == pf.game[curr_unit.row][curr_unit.col] - 1) + { + BN_LOG("NORTH"); + + curr_unit.row = curr_unit.row - 1; + curr_unit.y = curr_unit.y - 16; + curr_sprite.set_y(curr_unit.y); + curr_unit.movement_counter--; + } + else if(pf.is_valid(curr_unit.row, curr_unit.col - 1) && pf.game[curr_unit.row][curr_unit.col - 1] == pf.game[curr_unit.row][curr_unit.col] - 1) + { + BN_LOG("WEST"); + + curr_unit.col = curr_unit.col - 1; + curr_unit.x = curr_unit.x - 16; + curr_sprite.set_x(curr_unit.x); + curr_sprite.set_horizontal_flip(true); + curr_unit.movement_counter--; + } + + movement_counter = 0; + + } + movement_counter++; + // if(!tc.is_player_turn) + // { + // tc.turn_timer--; + // } +} + +void Util::vaild_moves(Pathfinder& pf, int row, int col, int count) +{ + if(!pf.is_valid(row, col) || count == 0 || pf.game[row][col] != -1) + return; + + pf.game[row][col] = count; + + vaild_moves(pf, row - 1, col, count - 1); //SOUTH + vaild_moves(pf, row + 1, col, count - 1); // NORTH + vaild_moves(pf, row, col - 1, count - 1); // WEST + vaild_moves(pf, row, col + 1, count - 1); // EAST +} + +void Util::hide_tiles(bn::sprite_ptr& v_tile_1, bn::sprite_ptr& v_tile_2, + bn::sprite_ptr& v_tile_3, bn::sprite_ptr& v_tile_4, bn::sprite_ptr& v_tile_5, bn::sprite_ptr& v_tile_6, + bn::sprite_ptr& v_tile_7, bn::sprite_ptr& v_tile_8, bn::sprite_ptr& v_tile_9, bn::sprite_ptr& v_tile_10, + bn::sprite_ptr& v_tile_11, bn::sprite_ptr& v_tile_12) +{ + v_tile_1.set_visible(false); + v_tile_2.set_visible(false); + v_tile_3.set_visible(false); + v_tile_4.set_visible(false); + + v_tile_5.set_visible(false); + v_tile_6.set_visible(false); + v_tile_7.set_visible(false); + v_tile_8.set_visible(false); + + v_tile_9.set_visible(false); + v_tile_10.set_visible(false); + v_tile_11.set_visible(false); + v_tile_12.set_visible(false); +} + +void Util::paint_moves_1(Unit& curr_unit,Pathfinder& pf, bn::sprite_ptr& v_tile_1, bn::sprite_ptr& v_tile_2, + bn::sprite_ptr& v_tile_3, bn::sprite_ptr& v_tile_4) +{ + int origin_pos_x = -104; int origin_pos_y = -73;//temp + if(pf.game[curr_unit.row + 1][curr_unit.col] == 2) + { + v_tile_1.set_position(origin_pos_x + (curr_unit.col * 16) , origin_pos_y + ((curr_unit.row + 1) * 16)); + v_tile_1.set_visible(true); + } + if(pf.game[curr_unit.row - 1][curr_unit.col] == 2) + { + v_tile_2.set_position(origin_pos_x + (curr_unit.col * 16) , origin_pos_y + ((curr_unit.row - 1) * 16)); + v_tile_2.set_visible(true); + } + if(pf.game[curr_unit.row][curr_unit.col + 1] == 2) + { + v_tile_3.set_position(origin_pos_x + ((curr_unit.col + 1) * 16) , origin_pos_y + (curr_unit.row * 16)); + v_tile_3.set_visible(true); + } + if(pf.game[curr_unit.row][curr_unit.col - 1] == 2) + { + v_tile_4.set_position(origin_pos_x + ((curr_unit.col - 1) * 16) , origin_pos_y + (curr_unit.row * 16)); + v_tile_4.set_visible(true); + } +} + +void Util::paint_moves_2(Unit& curr_unit,Pathfinder& pf, bn::sprite_ptr& v_tile_5, bn::sprite_ptr& v_tile_6, + bn::sprite_ptr& v_tile_7, bn::sprite_ptr& v_tile_8) +{ + int origin_pos_x = -104; int origin_pos_y = -73;//temp + if(pf.game[curr_unit.row + 2][curr_unit.col] == 1) + { + v_tile_5.set_position(origin_pos_x + (curr_unit.col * 16) , origin_pos_y + ((curr_unit.row + 2) * 16)); + v_tile_5.set_visible(true); + } + if(pf.game[curr_unit.row - 2][curr_unit.col] == 1) + { + v_tile_6.set_position(origin_pos_x + (curr_unit.col * 16) , origin_pos_y + ((curr_unit.row - 2) * 16)); + v_tile_6.set_visible(true); + } + if(pf.game[curr_unit.row][curr_unit.col + 2] == 1) + { + v_tile_7.set_position(origin_pos_x + ((curr_unit.col + 2) * 16) , origin_pos_y + (curr_unit.row * 16)); + v_tile_7.set_visible(true); + } + if(pf.game[curr_unit.row][curr_unit.col - 2] == 1) + { + v_tile_8.set_position(origin_pos_x + ((curr_unit.col - 2) * 16) , origin_pos_y + (curr_unit.row * 16)); + v_tile_8.set_visible(true); + } +} + +void Util::paint_moves_3(Unit& curr_unit,Pathfinder& pf, bn::sprite_ptr& v_tile_9, bn::sprite_ptr& v_tile_10, + bn::sprite_ptr& v_tile_11, bn::sprite_ptr& v_tile_12) +{ + int origin_pos_x = -104; int origin_pos_y = -73;//temp + if(pf.game[curr_unit.row - 1][curr_unit.col - 1] == 1) + { + v_tile_9.set_position(origin_pos_x + ((curr_unit.col -1) * 16) , origin_pos_y + ((curr_unit.row - 1) * 16)); + v_tile_9.set_visible(true); + } + if(pf.game[curr_unit.row - 1][curr_unit.col + 1] == 1) + { + v_tile_10.set_position(origin_pos_x + ((curr_unit.col + 1) * 16) , origin_pos_y + ((curr_unit.row - 1) * 16)); + v_tile_10.set_visible(true); + } + if(pf.game[curr_unit.row + 1][curr_unit.col - 1] == 1) + { + v_tile_11.set_position(origin_pos_x + ((curr_unit.col - 1) * 16) , origin_pos_y + ((curr_unit.row + 1) * 16)); + v_tile_11.set_visible(true); + } + if(pf.game[curr_unit.row + 1][curr_unit.col + 1] == 1) + { + v_tile_12.set_position(origin_pos_x + ((curr_unit.col + 1) * 16) , origin_pos_y + ((curr_unit.row + 1) * 16)); + v_tile_12.set_visible(true); + } +}