diff --git a/.vimrc b/.vimrc index 93f1473..579fddc 100644 --- a/.vimrc +++ b/.vimrc @@ -1,7 +1,7 @@ nnoremap :Make nnoremap :Make lint test nnoremap :Termdebug _build/breakhack -nnoremap :ter _build/breakhack +nnoremap :ter ++close ./_build/breakhack packadd termdebug let g:termdebug_wide = 1 diff --git a/CMakeLists.txt b/CMakeLists.txt index e9e5dbc..c133be0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ project(breakhack C) set(breakhack_GAME_TITLE "BreakHack") set(breakhack_MAJOR_VERSION 0) set(breakhack_MINOR_VERSION 1) -set(breakhack_PATCH_VERSION 6) +set(breakhack_PATCH_VERSION 7) set(breakhack_RELEASE_TYPE "(early access)") include(FindLua) @@ -171,6 +171,7 @@ add_executable(breakhack src/db src/settings src/actiontextbuilder + src/animation ) # Sqlite has some warnings that I we don't need to see diff --git a/README.md b/README.md index 64f221f..0294029 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ [![Build Status](https://travis-ci.org/LiquidityC/breakhack.svg?branch=master)](https://travis-ci.org/LiquidityC/breakhack) [![Build Status](https://ci.appveyor.com/api/projects/status/2nvna97cmm4cf535?svg=true)](https://ci.appveyor.com/project/LiquidityC/breakhack) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/fc02d56fa7194e61b2c7d260fd2e4186)](https://www.codacy.com/app/LiquidityC/breakhack?utm_source=github.com&utm_medium=referral&utm_content=LiquidityC/breakhack&utm_campaign=Badge_Grade) +[![CodeFactor](https://www.codefactor.io/repository/github/liquidityc/breakhack/badge/master)](https://www.codefactor.io/repository/github/liquidityc/breakhack/overview/master) Something in the ways of NETHACK diff --git a/assets/Extras/SwordSwing.png b/assets/Extras/SwordSwing.png new file mode 100644 index 0000000..bd8a783 Binary files /dev/null and b/assets/Extras/SwordSwing.png differ diff --git a/build/releasenotes/early-access-v7.txt b/build/releasenotes/early-access-v7.txt new file mode 100644 index 0000000..22963ac --- /dev/null +++ b/build/releasenotes/early-access-v7.txt @@ -0,0 +1,18 @@ +f36a9dd Sleeping state indicator is always visible. +53dc7e2 Possibly more accurate scaling. +dff55a1 Fixes some buggs +6a9a3bd Removed some old debug output from pitlayouts. +cc229c8 Prepares pengine for more particle types. +bbe4526 Fixes colors to use defines. +2462e4c Adds sentinel monster behaviour. +a66f16d Reintroduces the pointer and mouse menu operation. +123ae90 Better mod key logic in input and mouse motion check. +821cac2 Completely separates input handling and game logic. +186cc7b Replaced state logic with behaviours instead. +b905232 ....and once again... +8573bad ...and include the SDL dll +8c58c6e And once again for windows! +6788e3c Another trywq +60114ed Hopefully fixes the build issues +e222e51 Don't test on clang and fix include problem in appveyor +138cba1 Mock test for keyboardinput and fixed the found issues diff --git a/data/mapgen.lua b/data/mapgen.lua index b95ebfd..4531810 100644 --- a/data/mapgen.lua +++ b/data/mapgen.lua @@ -17,7 +17,7 @@ local function matrix_coverage (matrix) local cov = 0 for i=1,10 do for j=1,10 do - if matrix[i][j].active then cov = cov + 1 end + if matrix[i][j] then cov = cov + 1 end end end return cov @@ -36,7 +36,7 @@ local function generate_path () for i=1,10 do map_matrix[i] = {} for j=1,10 do - map_matrix[i][j] = room_builder.create_room() + map_matrix[i][j] = nil end end @@ -47,7 +47,10 @@ local function generate_path () local direction = 0 local lastDirection = 0 local coridoor_count = 0 - local coverage = 10 + local coverage = 9 + CURRENT_LEVEL + + -- Create the first room + map_matrix[cx][cy] = room_builder.create_empty_room() while matrix_coverage(map_matrix) < coverage do local direction = random(4) @@ -60,8 +63,6 @@ local function generate_path () direction = random(4) end - map_matrix[cx][cy].active = true - if coridoor_count < coverage/3 then if random(3) == 1 and (cx > 1 or cy > 1) then map_matrix[cx][cy].type = "coridoor" @@ -69,49 +70,56 @@ local function generate_path () end end + valid_direction = false if direction == UP and cy > 1 then -- UP - table.insert(map_matrix[cx][cy].exits, direction) + room_builder.add_exit(map_matrix[cx][cy], direction) map_matrix[cx][cy].path_dir = direction - cy = cy - 1; - table.insert(map_matrix[cx][cy].exits, reverse_direction(direction)) + cy = cy - 1 + valid_direction = true elseif direction == LEFT and cx > 1 then -- LEFT - table.insert(map_matrix[cx][cy].exits, direction) + room_builder.add_exit(map_matrix[cx][cy], direction) map_matrix[cx][cy].path_dir = direction - cx = cx - 1; - table.insert(map_matrix[cx][cy].exits, reverse_direction(direction)) + cx = cx - 1 + valid_direction = true elseif direction == RIGHT and cx < 10 then -- RIGHT - table.insert(map_matrix[cx][cy].exits, direction) + room_builder.add_exit(map_matrix[cx][cy], direction) map_matrix[cx][cy].path_dir = direction - cx = cx + 1; - table.insert(map_matrix[cx][cy].exits, reverse_direction(direction)) + cx = cx + 1 + valid_direction = true elseif direction == DOWN and cy < 10 then -- DOWN - table.insert(map_matrix[cx][cy].exits, direction) + room_builder.add_exit(map_matrix[cx][cy], direction) map_matrix[cx][cy].path_dir = direction - cy = cy + 1; - table.insert(map_matrix[cx][cy].exits, reverse_direction(direction)) + cy = cy + 1 + valid_direction = true + end + + -- Create the next room and add the reverse exit + -- if a valid direction was found + if valid_direction then + if not map_matrix[cx][cy] then + map_matrix[cx][cy] = room_builder.create_empty_room() + end + room_builder.add_exit(map_matrix[cx][cy], reverse_direction(direction)) end lastDirection = direction end -- Last room rules - map_matrix[cx][cy].active = true map_matrix[cx][cy].goal = true map_matrix[cx][cy].type = "room" - return map_matrix; -end - -local function print_matrix(matrix) + -- Build all the rooms for i=1,10 do for j=1,10 do - if not map_matrix[j][i].goal then - io.write(map_matrix[j][i].path_dir .. " ") - else - io.write("G ") + room = map_matrix[i][j] + if room then + room_builder.build_room(room) + monster_gen.add_monsters_to_room(room, i-1, j-1) end end - io.write("\n") end + + return map_matrix; end -- END FUNCTIONS @@ -126,14 +134,10 @@ local map_matrix = generate_path() for i=1,10 do for j=1,10 do local room = map_matrix[i][j] - if room.active then + if room then set_current_room(map, i-1, j-1); - if room.type == "room" then - room_builder.build_square_room(map, room) - monster_gen.add_monster_to_room(map, i-1, j-1); - elseif room.type == "coridoor" then - room_builder.build_coridoor_room(map, room) - end + room_builder.load_room(map, room) + monster_gen.load_monsters(map, room.monsters) end end end diff --git a/data/maproombuilder.lua b/data/maproombuilder.lua index fab6b90..c230503 100644 --- a/data/maproombuilder.lua +++ b/data/maproombuilder.lua @@ -61,23 +61,23 @@ local function load_decor_textures() table.insert(floorDecor, { td0, td1, 48, 13 * 16, false, false }) -- Urns - table.insert(floorDecor, { td0, td1, 0 * 16, 48, true, false }) - table.insert(floorDecor, { td0, td1, 1 * 16, 48, true, false }) - table.insert(floorDecor, { td0, td1, 2 * 16, 48, true, false }) - table.insert(floorDecor, { td0, td1, 3 * 16, 48, true, false }) - table.insert(floorDecor, { td0, td1, 4 * 16, 48, true, false }) - table.insert(floorDecor, { td0, td1, 5 * 16, 48, true, false }) - table.insert(floorDecor, { td0, td1, 6 * 16, 48, false, false }) - table.insert(floorDecor, { td0, td1, 7 * 16, 48, false, false }) + --table.insert(floorDecor, { td0, td1, 0 * 16, 48, true, false }) + --table.insert(floorDecor, { td0, td1, 1 * 16, 48, true, false }) + --table.insert(floorDecor, { td0, td1, 2 * 16, 48, true, false }) + --table.insert(floorDecor, { td0, td1, 3 * 16, 48, true, false }) + --table.insert(floorDecor, { td0, td1, 4 * 16, 48, true, false }) + --table.insert(floorDecor, { td0, td1, 5 * 16, 48, true, false }) + --table.insert(floorDecor, { td0, td1, 6 * 16, 48, false, false }) + --table.insert(floorDecor, { td0, td1, 7 * 16, 48, false, false }) -- Racks - table.insert(floorDecor, { td0, td1, 0 * 16, 11 * 16, true, false }) - table.insert(floorDecor, { td0, td1, 1 * 16, 11 * 16, true, false }) - table.insert(floorDecor, { td0, td1, 2 * 16, 11 * 16, true, false }) - table.insert(floorDecor, { td0, td1, 3 * 16, 11 * 16, true, false }) - table.insert(floorDecor, { td0, td1, 4 * 16, 11 * 16, true, false }) - table.insert(floorDecor, { td0, td1, 5 * 16, 11 * 16, true, false }) - table.insert(floorDecor, { td0, td1, 6 * 16, 11 * 16, true, false }) + --table.insert(floorDecor, { td0, td1, 0 * 16, 11 * 16, true, false }) + --table.insert(floorDecor, { td0, td1, 1 * 16, 11 * 16, true, false }) + --table.insert(floorDecor, { td0, td1, 2 * 16, 11 * 16, true, false }) + --table.insert(floorDecor, { td0, td1, 3 * 16, 11 * 16, true, false }) + --table.insert(floorDecor, { td0, td1, 4 * 16, 11 * 16, true, false }) + --table.insert(floorDecor, { td0, td1, 5 * 16, 11 * 16, true, false }) + --table.insert(floorDecor, { td0, td1, 6 * 16, 11 * 16, true, false }) -- Headstones table.insert(floorDecor, { td0, td1, 0 * 16, 17 * 16, true, false }) @@ -138,22 +138,31 @@ local function check_add_decoration(map, x, y, data) return true end -local function check_add_tile(map, x, y, data) - if tile_occupied(map, x, y) then - return false - end - add_tile(map, x, y, repack(data)) - return true -end - -local function add_random_decor_to_room(map) +local function add_random_decor_to_room(room) local decor_count = random(4) - 1 for i=1,decor_count do - check_add_decoration(map, random(11)+1, random(8)+1, floorDecor[random(#floorDecor)]) + x = random(11) + 1 + y = random(8) + 1 + if not room.decor[x][y] then + room.decor[x][y] = floorDecor[random(#floorDecor)] + end + end + + if random(2) == 1 then + room.decor[4][3] = lightDecor.candle2 + end + if random(2) == 1 then + room.decor[11][3] = lightDecor.candle2 + end + if random(2) == 1 then + room.decor[4][9] = lightDecor.candle2 + end + if random(2) == 1 then + room.decor[11][9] = lightDecor.candle2 end end -local function add_pits_to_room(map) +local function add_pits_to_room(room) if CURRENT_LEVEL < 3 then return @@ -189,210 +198,177 @@ local function add_pits_to_room(map) -- Chose a random layout matrix = matrix[random(#matrix)] - for i=2,13 do for j=2,10 do - if not tile_occupied(map, (i), (j)) and matrix[i][j] then + if matrix[i][j] then + room.decor[i][j] = nil if not matrix[i-1][j-1] and not matrix[i+1][j-1] and matrix[i-1][j] and matrix[i+1][j] and matrix[i][j-1] then - add_tile(map, i, j, repack(pits.innermid)) + room.tiles[i][j] = pits.innermid elseif not matrix[i-1][j-1] and matrix[i-1][j] and matrix[i][j-1] then - add_tile(map, i, j, repack(pits.innerleft)) + room.tiles[i][j] = pits.innerleft elseif not matrix[i+1][j-1] and matrix[i+1][j] and matrix[i][j-1] then - add_tile(map, i, j, repack(pits.innerright)) + room.tiles[i][j] = pits.innerright elseif not matrix[i-1][j] and not matrix[i][j-1] and not matrix[i+1][j] then - add_tile(map, i, j, repack(pits.topcrevice)) + room.tiles[i][j] = pits.topcrevice elseif not matrix[i-1][j] and not matrix[i+1][j] then - add_tile(map, i, j, repack(pits.bottomcrevice)) + room.tiles[i][j] = pits.bottomcrevice elseif not matrix[i-1][j] and not matrix[i][j-1] then - add_tile(map, i, j, repack(pits.topleft)) + room.tiles[i][j] = pits.topleft elseif not matrix[i+1][j] and not matrix[i][j-1] then - add_tile(map, i, j, repack(pits.topright)) + room.tiles[i][j] = pits.topright elseif not matrix[i-1][j] then - add_tile(map, i, j, repack(pits.left)) + room.tiles[i][j] = pits.left elseif not matrix[i+1][j] then - add_tile(map, i, j, repack(pits.right)) + room.tiles[i][j] = pits.right elseif not matrix[i][j-1] then - add_tile(map, i, j, repack(pits.top)) + room.tiles[i][j] = pits.top else - add_tile(map, i, j, repack(pits.center)) + room.tiles[i][j] = pits.center end end end end end -local function add_tiles_to_room (map) +local function add_tiles_to_room (room) for i=0,15 do for j=0,11 do if (i >= 1 and i <= 14 and j >= 1 and j <= 10) then if (i == 1 and j == 1) then - add_tile(map, i, j, repack(floor.topleft)) + room.tiles[i][j] = floor.topleft elseif (i == 14 and j == 1) then - add_tile(map, i, j, repack(floor.topright)) + room.tiles[i][j] = floor.topright elseif (i == 1 and j == 10) then - add_tile(map, i, j, repack(floor.bottomleft)) + room.tiles[i][j] = floor.bottomleft elseif (i == 14 and j == 10) then - add_tile(map, i, j, repack(floor.bottomright)) + room.tiles[i][j] = floor.bottomright elseif (i == 1) then - add_tile(map, i, j, repack(floor.left)) + room.tiles[i][j] = floor.left elseif (i == 14) then - add_tile(map, i, j, repack(floor.right)) + room.tiles[i][j] = floor.right elseif (j == 1) then - add_tile(map, i, j, repack(floor.top)) + room.tiles[i][j] = floor.top elseif (j == 10) then - add_tile(map, i, j, repack(floor.bottom)) + room.tiles[i][j] = floor.bottom else - add_tile(map, i, j, repack(floor.center)) + room.tiles[i][j] = floor.center end end end end - - add_random_decor_to_room(map) - add_pits_to_room(map) end -local function add_walls_to_room (map) +local function add_walls_to_room (room) for i=0,15 do for j=0,11 do if (i == 0 and j == 0) then - add_tile(map, i, j, repack(wall.topleft)) + room.tiles[i][j] = wall.topleft elseif (i == 15 and j == 0) then - add_tile(map, i, j, repack(wall.topright)) + room.tiles[i][j] = wall.topright elseif (i == 0 and j == 11) then - add_tile(map, i, j, repack(wall.bottomleft)) + room.tiles[i][j] = wall.bottomleft elseif (i == 15 and j == 11) then - add_tile(map, i, j, repack(wall.bottomright)) + room.tiles[i][j] = wall.bottomright elseif (i == 0 or i == 15) then - add_tile(map, i, j, repack(wall.vertical)) + room.tiles[i][j] = wall.vertical elseif (j == 0 or j == 11) then - add_tile(map, i, j, repack(wall.horizontal)) + room.tiles[i][j] = wall.horizontal end end end - - if random(2) == 1 then - check_add_decoration(map, 4, 3, lightDecor.candle2) - end - if random(2) == 1 then - check_add_decoration(map, 11, 3, lightDecor.candle2) - end - if random(2) == 1 then - check_add_decoration(map, 4, 9, lightDecor.candle2) - end - if random(2) == 1 then - check_add_decoration(map, 11, 9, lightDecor.candle2) - end end -local function add_exit(map, direction) - if direction > 4 then return end - - if direction == UP then - add_tile(map, 6, 0, repack(wall.bottomright)) - add_tile(map, 7, 0, repack(floor.singleleft)) - add_tile(map, 8, 0, repack(floor.singleright)) - add_tile(map, 9, 0, repack(wall.bottomleft)) - elseif direction == LEFT then - add_tile(map, 0, 4, repack(wall.bottomright)) - add_tile(map, 0, 5, repack(floor.singletop)) - add_tile(map, 0, 6, repack(floor.singlebottom)) - add_tile(map, 0, 7, repack(wall.topright)) - elseif direction == RIGHT then - add_tile(map, 15, 4, repack(wall.bottomleft)) - add_tile(map, 15, 5, repack(floor.singletop)) - add_tile(map, 15, 6, repack(floor.singlebottom)) - add_tile(map, 15, 7, repack(wall.topleft)) - elseif direction == DOWN then - add_tile(map, 6, 11, repack(wall.topright)) - add_tile(map, 7, 11, repack(floor.singleleft)) - add_tile(map, 8, 11, repack(floor.singleright)) - add_tile(map, 9, 11, repack(wall.topleft)) - end -end - -local function add_level_exit(map) - success = false - while not success do - x = random(14) - y = random(10) - success = check_add_tile(map, x, y, special.level_exit) - end -end - -local function build_vert_center_coridoor(map, offset) - for j=0,4 do - add_tile(map, 6, offset+j, repack(wall.vertical)); - add_tile(map, 7, offset+j, repack(floor.center)); - add_tile(map, 8, offset+j, repack(floor.center)); - add_tile(map, 9, offset+j, repack(wall.vertical)); +local function build_vert_center_coridoor(room, offset) + for i=0,4 do + room.tiles[6][offset+i] = wall.vertical + room.tiles[7][offset+i] = floor.center + room.tiles[8][offset+i] = floor.center + room.tiles[9][offset+i] = wall.vertical end if random(2) == 1 then - add_decoration(map, 6, offset + 2, repack(lightDecor.candle1)) + room.decor[6][offset+2] = lightDecor.candle1 end if random(2) == 1 then - add_decoration(map, 9, offset + 2, repack(lightDecor.candle1)) + room.decor[6][offset+2] = lightDecor.candle1 end end -local function build_horiz_center_coridoor(map, offset) +local function build_horiz_center_coridoor(room, offset) + info("Building horizontal corrdior: " .. offset) for i=0,6 do - add_tile(map, offset+i, 4, repack(wall.horizontal)); - add_tile(map, offset+i, 5, repack(floor.center)); - add_tile(map, offset+i, 6, repack(floor.center)); - add_tile(map, offset+i, 7, repack(wall.horizontal)); + room.tiles[offset+i][4] = wall.horizontal + room.tiles[offset+i][5] = floor.center + room.tiles[offset+i][6] = floor.center + room.tiles[offset+i][7] = wall.horizontal end if random(2) == 1 then - check_add_decoration(map, offset+3, 4, lightDecor.candle1) + room.decor[offset+3][4] = lightDecor.candle1 end if random(2) == 1 then - check_add_decoration(map, offset+3, 7, lightDecor.candle1) + room.decor[offset+3][7] = lightDecor.candle1 end end -local function build_center_corner_walls(map, exits) +local function build_center_corner_walls(room, exits) if exits.down then if exits.left then - add_tile(map, 6, 7, repack(wall.topright)) + room.tiles[6][7] = wall.topright end if exits.right then - add_tile(map, 9, 7, repack(wall.topleft)) + room.tiles[9][7] = wall.topleft end else if not exits.left then - add_tile(map, 6, 7, repack(wall.bottomleft)) + room.tiles[6][7] = wall.bottomleft end if not exits.right then - add_tile(map, 9, 7, repack(wall.bottomright)) + room.tiles[9][7] = wall.bottomright end end if exits.up then if exits.left then - add_tile(map, 6, 4, repack(wall.bottomright)) + room.tiles[6][4] = wall.bottomright end if exits.right then - add_tile(map, 9, 4, repack(wall.bottomleft)) + room.tiles[9][4] = wall.bottomleft end else if not exits.left then - add_tile(map, 6, 4, repack(wall.topleft)) + room.tiles[6][4] = wall.topleft end if not exits.right then - add_tile(map, 9, 4, repack(wall.topright)) + room.tiles[9][4] = wall.topright end end end -local module = {} - -function module.add_full_lighting(map) - check_add_decoration(map, 4, 3, lightDecor.candle2) - check_add_decoration(map, 11, 3, lightDecor.candle2) - check_add_decoration(map, 4, 9, lightDecor.candle2) - check_add_decoration(map, 11, 9, lightDecor.candle2) +local function add_exits_to_room(room) + for _,direction in ipairs(room.exits) do + if direction == UP then + room.tiles[6][0] = wall.bottomright + room.tiles[7][0] = floor.singleleft + room.tiles[8][0] = floor.singleright + room.tiles[9][0] = wall.bottomleft + elseif direction == LEFT then + room.tiles[0][4] = wall.bottomright + room.tiles[0][5] = floor.singletop + room.tiles[0][6] = floor.singlebottom + room.tiles[0][7] = wall.topright + elseif direction == RIGHT then + room.tiles[15][4] = wall.bottomleft + room.tiles[15][5] = floor.singletop + room.tiles[15][6] = floor.singlebottom + room.tiles[15][7] = wall.topleft + elseif direction == DOWN then + room.tiles[6][11] = wall.topright + room.tiles[7][11] = floor.singleleft + room.tiles[8][11] = floor.singleright + room.tiles[9][11] = wall.topleft + end + end end -function module.build_coridoor_room(map, room) +local function build_coridoor_room(room) local exits = { up = false, down = false, @@ -409,51 +385,126 @@ function module.build_coridoor_room(map, room) end -- Fill the center - add_tile(map, 6, 5, repack(wall.vertical)) - add_tile(map, 6, 6, repack(wall.vertical)) - add_tile(map, 7, 4, repack(wall.horizontal)) - add_tile(map, 7, 5, repack(floor.center)) - add_tile(map, 7, 6, repack(floor.center)) - add_tile(map, 7, 7, repack(wall.horizontal)) - add_tile(map, 8, 4, repack(wall.horizontal)) - add_tile(map, 8, 5, repack(floor.center)) - add_tile(map, 8, 6, repack(floor.center)) - add_tile(map, 8, 7, repack(wall.horizontal)) - add_tile(map, 9, 5, repack(wall.vertical)) - add_tile(map, 9, 6, repack(wall.vertical)) + room.tiles[6][5] = wall.vertical + room.tiles[6][6] = wall.vertical + room.tiles[7][4] = wall.horizontal + room.tiles[7][5] = floor.center + room.tiles[7][6] = floor.center + room.tiles[7][7] = wall.horizontal + room.tiles[8][4] = wall.horizontal + room.tiles[8][5] = floor.center + room.tiles[8][6] = floor.center + room.tiles[8][7] = wall.horizontal + room.tiles[9][5] = wall.vertical + room.tiles[9][6] = wall.vertical -- Build the coridoors - if exits.down then build_vert_center_coridoor(map, 7) end - if exits.up then build_vert_center_coridoor(map, 0) end - if exits.left then build_horiz_center_coridoor(map, 0) end - if exits.right then build_horiz_center_coridoor(map, 9) end + if exits.down then build_vert_center_coridoor(room, 7) end + if exits.up then build_vert_center_coridoor(room, 0) end + if exits.left then build_horiz_center_coridoor(room, 0) end + if exits.right then build_horiz_center_coridoor(room, 9) end - build_center_corner_walls(map, exits) + build_center_corner_walls(room, exits) end -function module.create_room () - return { - exits = {}, - active = false, - goal = false, - path_dir = 0, - type = "room" - } -end - -function module.build_square_room(map, room) - add_tiles_to_room(map); - add_walls_to_room(map); - for exit=1, #room.exits do - add_exit(map, room.exits[exit]); +local function add_level_exit(room) + success = false + while not success do + x = random(14) + y = random(10) + if not room.decor[x][y] then + success = true + room.tiles[x][y] = special.level_exit + end end +end + +local function build_normal_room(room) + add_tiles_to_room(room) + add_random_decor_to_room(room) + add_walls_to_room(room) + add_exits_to_room(room) + add_pits_to_room(room) + if room.goal then - add_level_exit(map); + add_level_exit(room) end if CURRENT_LEVEL > 3 and random(10) == 1 then directions = { "LEFT", "RIGHT", "UP", "DOWN" } - set_modifier(map, "WINDY", directions[random(#directions)]); + room.modifier.type = "WINDY" + room.modifier.arg = directions[random(#directions)] + end + + return room +end + +local module = {} + +function module.add_exit(room, direction) + if direction > 4 then + return + end + + table.insert(room.exits, direction) +end + +function module.add_full_lighting(room) + room.decor[4][3] = lightDecor.candle2 + room.decor[11][3] = lightDecor.candle2 + room.decor[4][9] = lightDecor.candle2 + room.decor[11][9] = lightDecor.candle2 +end + +function module.create_empty_room() + room = { + exits = {}, + active = false, + goal = false, + path_dir = 0, + type = "room", + tiles = {}, + decor = {}, + modifier = { + type = nil, + arg = nil + }, + monsters = {} + } + for i=0,15 do + room.tiles[i] = {} + room.decor[i] = {} + room.monsters[i] = {} + for j=0,11 do + room.tiles[i][j] = nil + room.decor[i][j] = nil + room.monsters[i][j] = nil + end + end + return room +end + +function module.build_room(room) + if room.type == "coridoor" then + build_coridoor_room(room) + else + build_normal_room(room) + end +end + +function module.load_room(map, room) + for i=0, 15 do + for j=0, 11 do + if room.tiles[i][j] then + add_tile(map, i, j, repack(room.tiles[i][j])) + end + if room.decor[i][j] then + add_decoration(map, i, j, repack(room.decor[i][j])) + end + end + end + if room.modifier.type then + set_modifier(map, room.modifier.type, room.modifier.arg) end end diff --git a/data/menumapgen.lua b/data/menumapgen.lua index 661b052..f446c6b 100644 --- a/data/menumapgen.lua +++ b/data/menumapgen.lua @@ -4,9 +4,11 @@ local monster_gen = require "monstergen" map = create_map(CURRENT_LEVEL) -- 'map' needs to be global room_builder.load_textures(map) -local room = room_builder.create_room() set_current_room(map, 0, 0) -room_builder.build_square_room(map, room) -monster_gen.add_monster_to_room(map, 0, 0); -room_builder.add_full_lighting(map); +local room = room_builder.create_empty_room() +room_builder.build_room(room) +room_builder.add_full_lighting(room) +monster_gen.add_monsters_to_room(room, 0, 0) +room_builder.load_room(map, room) +monster_gen.load_monsters(map, room.monsters) diff --git a/data/monstergen.lua b/data/monstergen.lua index b116c4f..e6b33ad 100644 --- a/data/monstergen.lua +++ b/data/monstergen.lua @@ -241,15 +241,42 @@ if random(100) == 1 then enemies = concat(enemies, platino); end -function module.add_monster_to_room(map, roomx, roomy) +function module.add_monsters_to_room(room, roomx, roomy) local count = random(3) if (CURRENT_LEVEL > 3) then count = random(4) end - for i=0,count do - local x = (roomx * 512) + (random(13) + 1) * 32 - local y = (roomy * 384) + (random(9) + 1) * 32 - add_monster(map, x, y, repack(enemies[random(#enemies)])); + local i = 0 + while i < count do + local rx = random(13) + 1 + local ry = random(9) + 1 + if not room.decor[rx][ry] + and not room.monsters[rx][ry] + and (room.tiles[rx][ry] + and not room.tiles[rx][ry][5] + and not room.tiles[rx][ry][8]) + then + + local x = (roomx * 512) + rx * 32 + local y = (roomy * 384) + ry * 32 + room.monsters[rx][ry] = { + x, + y, + enemies[random(#enemies)] + } + i = i + 1 + end + end +end + +function module.load_monsters(map, monsters) + for i=0,15 do + for j=0,11 do + monster = monsters[i][j] + if monster then + add_monster(map, monster[1], monster[2], repack(monster[3])) + end + end end end diff --git a/src/animation.c b/src/animation.c new file mode 100644 index 0000000..cd63542 --- /dev/null +++ b/src/animation.c @@ -0,0 +1,117 @@ +/* + * BreakHack - A dungeone crawler RPG + * Copyright (C) 2018 Linus Probert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "animation.h" +#include "timer.h" +#include "camera.h" +#include "sprite.h" +#include "util.h" + +Animation * +animation_create(unsigned int clipCount) +{ + Animation *animation = ec_malloc(sizeof(Animation) + + clipCount * sizeof(AnimationClip)); + animation->clipTimer = timer_create(); + animation->clipCount = clipCount; + animation->currentClip = 0; + animation->loop = true; + animation->running = false; + animation->sprite = sprite_create(); + return animation; +} + +void +animation_load_texture(Animation *animation, const char *path, SDL_Renderer *renderer) +{ + sprite_load_texture(animation->sprite, path, 0, renderer); +} + +void +animation_update(Animation *animation) +{ + if (!animation->running) { + return; + } + + if (!timer_started(animation->clipTimer)) { + timer_start(animation->clipTimer); + } + + if (timer_get_ticks(animation->clipTimer) + > animation->clips[animation->currentClip].renderTime) + { + animation->currentClip++; + if (animation->currentClip >= animation->clipCount) { + animation->currentClip = 0; + if (!animation->loop) { + animation_stop(animation); + return; + } + timer_start(animation->clipTimer); + } + } + + animation->sprite->clip = (SDL_Rect) { + animation->clips[animation->currentClip].x, + animation->clips[animation->currentClip].y, + animation->clips[animation->currentClip].w, + animation->clips[animation->currentClip].h + }; +} + +void +animation_render(Animation *animation, Camera *camera) +{ + if (!animation->running) { + return; + } + + sprite_render(animation->sprite, camera); +} + +void +animation_set_frames(Animation *animation, AnimationClip clips[]) +{ + for (size_t i = 0; i < animation->clipCount; i++) { + animation->clips[i] = clips[i]; + } +} + +void +animation_run(Animation *a) +{ + a->running = true; +} + +void +animation_stop(Animation *a) +{ + a->running = false; + a->currentClip = 0; + timer_stop(a->clipTimer); +} + +void +animation_destroy(Animation *animation) +{ + timer_destroy(animation->clipTimer); + sprite_destroy(animation->sprite); + free(animation); +} + diff --git a/src/animation.h b/src/animation.h new file mode 100644 index 0000000..b6f8031 --- /dev/null +++ b/src/animation.h @@ -0,0 +1,75 @@ +/* + * BreakHack - A dungeone crawler RPG + * Copyright (C) 2018 Linus Probert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _ANIMATION_H +#define _ANIMATION_H + +#include +#include + +typedef struct Timer Timer; +typedef struct Camera Camera; +typedef struct Sprite Sprite; + +typedef struct AnimationClip +{ + unsigned int x; + unsigned int y; + unsigned int w; + unsigned int h; + unsigned int renderTime; +} AnimationClip; + +typedef struct Animation +{ + Sprite *sprite; + Timer *clipTimer; + unsigned int currentClip; + bool loop; + unsigned int clipCount; + bool running; + AnimationClip clips[]; +} Animation; + +Animation* +animation_create(unsigned int clipCount); + +void +animation_load_texture(Animation *, const char *path, SDL_Renderer*); + +void +animation_set_frames(Animation*, AnimationClip clips[]); + +void +animation_run(Animation*); + +void +animation_update(Animation*); + +void +animation_render(Animation*, Camera*); + +void +animation_stop(Animation*); + +void +animation_destroy(Animation*); + +#endif // _ANIMATION_H + + diff --git a/src/camera.h b/src/camera.h index 3dbae66..9fb876b 100644 --- a/src/camera.h +++ b/src/camera.h @@ -25,7 +25,7 @@ #include "timer.h" #include "vector2d.h" -typedef struct { +typedef struct Camera { Position pos; Position basePos; Vector2d velocity; diff --git a/src/linkedlist.h b/src/linkedlist.h index 919a3ea..3496bd1 100644 --- a/src/linkedlist.h +++ b/src/linkedlist.h @@ -42,6 +42,5 @@ void linkedlist_each(LinkedList **head, void (*fun)(void*)); void linkedlist_destroy(LinkedList **head); unsigned int linkedlist_size(LinkedList *head); - #endif // LINKEDLIST_H_ diff --git a/src/main.c b/src/main.c index df37918..82f3002 100644 --- a/src/main.c +++ b/src/main.c @@ -108,10 +108,6 @@ bool initSDL(void) if (dim.height > 1080) { info("Hi resolution screen detected (%u x %u)", dim.width, dim.height); renderScale = ((double) dim.height)/1080; - if (renderScale > 2) - renderScale = 3; - else if (renderScale > 1) - renderScale = 2; info("Scaling by %f", renderScale); } @@ -250,6 +246,7 @@ goToMainMenu(void *unused) inGameMenu = NULL; initMainMenu(); Position p = { 0, 0 }; + gPlayer->sprite->pos = (Position) { 32, 32 }; map_set_current_room(gMap, &p); camera_follow_position(gCamera, &p); } @@ -298,6 +295,22 @@ initInGameMenu(void) createMenu(&inGameMenu, menu_items, 3); } +static void +createInGameGameOverMenu(void) +{ + struct MENU_ITEM menu_items[] = { + { "NEW GAME", startGame }, + { "MAIN MENU", goToMainMenu }, + { "QUIT", exitGame }, + }; + + if (inGameMenu) { + menu_destroy(inGameMenu); + inGameMenu = NULL; + } + createMenu(&inGameMenu, menu_items, 3); +} + static void initMainMenu(void) { @@ -315,6 +328,15 @@ initMainMenu(void) mixer_play_music(MENU_MUSIC); } +static void +repopulate_roommatrix(void) +{ + roommatrix_populate_from_map(gRoomMatrix, gMap); + roommatrix_add_lightsource(gRoomMatrix, + &gPlayer->sprite->pos); + roommatrix_build_lightmap(gRoomMatrix); +} + static void resetGame(void) { @@ -341,6 +363,7 @@ resetGame(void) map_set_current_room(gMap, &gPlayer->sprite->pos); camera_follow_position(gCamera, &gPlayer->sprite->pos); + repopulate_roommatrix(); } static bool @@ -461,7 +484,7 @@ populateUpdateData(UpdateData *data, float deltatime) } static void -run_game(void) +run_game_update(void) { static UpdateData updateData; static unsigned int playerLevel = 1; @@ -471,11 +494,6 @@ run_game(void) map_clear_dead_monsters(gMap, gPlayer); map_clear_collected_items(gMap); - roommatrix_populate_from_map(gRoomMatrix, gMap); - roommatrix_add_lightsource(gRoomMatrix, - &gPlayer->sprite->pos); - - roommatrix_build_lightmap(gRoomMatrix); populateUpdateData(&updateData, deltaTime); if (playerLevel != gPlayer->stats.lvl) { @@ -500,13 +518,19 @@ run_game(void) if (player_turn_over(gPlayer)) { currentTurn = MONSTER; player_reset_steps(gPlayer); + repopulate_roommatrix(); } } else if (currentTurn == MONSTER) { if (map_move_monsters(gMap, gRoomMatrix)) { currentTurn = PLAYER; + repopulate_roommatrix(); } } +} +static void +run_game_render(void) +{ SDL_SetRenderDrawColor(gRenderer, 0, 0, 0, 0); SDL_RenderClear(gRenderer); @@ -519,6 +543,9 @@ run_game(void) map_render_top_layer(gMap, gCamera); + if (!is_player_dead()) + player_render_toplayer(gPlayer, gCamera); + if (gPlayer->class == MAGE || gPlayer->class == PALADIN) roommatrix_render_mouse_square(gRoomMatrix, gCamera); @@ -547,6 +574,14 @@ run_game(void) pointer_render(gPointer, gCamera); SDL_RenderPresent(gRenderer); +} + +static void +run_game(void) +{ + run_game_update(); + + run_game_render(); if (gGameState == PLAYING && is_player_dead()) { camera_shake(VECTOR2D_RIGHT, 800); @@ -554,6 +589,8 @@ run_game(void) gui_event_message("You died!"); mixer_play_effect(SPLAT); gGameState = GAME_OVER; + createInGameGameOverMenu(); + toggleInGameMenu(NULL); } else { check_next_level(); } diff --git a/src/menu.c b/src/menu.c index 9c9520c..e0cac1a 100644 --- a/src/menu.c +++ b/src/menu.c @@ -27,7 +27,7 @@ #include "mixer.h" #include "collisions.h" -typedef struct MenuItems_t { +typedef struct MenuItems { Sprite *sprite; Sprite *hsprite; GuiButton *button; diff --git a/src/monster.c b/src/monster.c index 9577cf7..3c5c7c6 100644 --- a/src/monster.c +++ b/src/monster.c @@ -66,7 +66,11 @@ monster_state_change(Monster *m, StateType newState) m->state.current = newState; m->state.stepsSinceChange = 0; - m->stateIndicator.displayCount = 5; + + if (newState == SLEEPING) + m->stateIndicator.displayCount = -1; + else + m->stateIndicator.displayCount = 5; monster_set_sprite_clip_for_current_state(m); } @@ -241,8 +245,8 @@ monster_drunk_walk(Monster *m, RoomMatrix *rm) } } -static void -monster_agressive_walk(Monster *m, RoomMatrix *rm) +static Direction +get_optimal_move_towards(Monster *m, RoomMatrix *rm, const Position *dest) { int x_dist, y_dist; Position mPos; @@ -257,21 +261,21 @@ monster_agressive_walk(Monster *m, RoomMatrix *rm) unsigned int nextScore = 0; switch (i) { - case UP: - next.y -= 1; - break; - case DOWN: - next.y += 1; - break; - case LEFT: - next.x -= 1; - break; - case RIGHT: - next.x += 1; - break; + case UP: + next.y -= 1; + break; + case DOWN: + next.y += 1; + break; + case LEFT: + next.x -= 1; + break; + case RIGHT: + next.x += 1; + break; } - if (position_equals(&next, &rm->playerRoomPos)) { + if (position_equals(&next, dest)) { chosenDirection = (Direction) i; break; } @@ -279,8 +283,8 @@ monster_agressive_walk(Monster *m, RoomMatrix *rm) if (!position_in_roommatrix(&next)) continue; - x_dist = abs(next.x - rm->playerRoomPos.x); - y_dist = abs(next.y - rm->playerRoomPos.y); + x_dist = abs(next.x - dest->x); + y_dist = abs(next.y - dest->y); if (rm->spaces[next.x][next.y].occupied || rm->spaces[next.x][next.y].lethal) { nextScore += 50; @@ -289,23 +293,31 @@ monster_agressive_walk(Monster *m, RoomMatrix *rm) nextScore += x_dist > y_dist ? x_dist : y_dist; if (nextScore < currentScore) { currentScore = nextScore; - chosenDirection = (Direction)i; + chosenDirection = (Direction) i; } } + return chosenDirection; +} + +static void +monster_agressive_walk(Monster *m, RoomMatrix *rm) +{ + unsigned int chosenDirection = get_optimal_move_towards(m, rm, &rm->playerRoomPos); + switch (chosenDirection) { - case UP: - move(m, rm, VECTOR2D_UP); - break; - case DOWN: - move(m, rm, VECTOR2D_DOWN); - break; - case LEFT: - move(m, rm, VECTOR2D_LEFT); - break; - case RIGHT: - move(m, rm, VECTOR2D_RIGHT); - break; + case UP: + move(m, rm, VECTOR2D_UP); + break; + case DOWN: + move(m, rm, VECTOR2D_DOWN); + break; + case LEFT: + move(m, rm, VECTOR2D_LEFT); + break; + case RIGHT: + move(m, rm, VECTOR2D_RIGHT); + break; } } @@ -320,7 +332,6 @@ monster_coward_walk(Monster *m, RoomMatrix *rm) x_dist = mPos.x - rm->playerRoomPos.x; y_dist = mPos.y - rm->playerRoomPos.y; - if (abs(x_dist) > abs(y_dist)) { if (x_dist > 0) move(m, rm, VECTOR2D_RIGHT); @@ -389,7 +400,9 @@ monster_update(Monster *m, UpdateData *data) return; m->stateIndicator.shownOnPlayerRoomEnter = true; - if (m->state.current != PASSIVE && m->state.current != STATIONARY) + if (m->state.current == SLEEPING) + m->stateIndicator.displayCount = -1; // Sleeping state is always shown + else if (m->state.current != PASSIVE && m->state.current != STATIONARY) m->stateIndicator.displayCount = 5; } else { m->stateIndicator.shownOnPlayerRoomEnter = false; @@ -486,7 +499,7 @@ monster_render(Monster *m, Camera *cam) return; sprite_render(m->sprite, cam); - if (m->stateIndicator.displayCount > 0) + if (m->stateIndicator.displayCount != 0) sprite_render(m->stateIndicator.sprite, cam); } diff --git a/src/particle_engine.c b/src/particle_engine.c index a9fa878..18dbdd6 100644 --- a/src/particle_engine.c +++ b/src/particle_engine.c @@ -252,7 +252,7 @@ particle_engine_sparkle(Position pos, Dimension dim) alpha = get_random(155) + 100; - yv = (get_random(100) + 100) * -1; + yv = -(get_random(100) + 100); lt = get_random(20); diff --git a/src/player.c b/src/player.c index 70c6a4f..7cf16de 100644 --- a/src/player.c +++ b/src/player.c @@ -33,6 +33,7 @@ #include "texturecache.h" #include "vector2d.h" #include "actiontextbuilder.h" +#include "animation.h" #define ENGINEER_STATS { 12, 12, 5, 7, 2, 2, 1 } #define MAGE_STATS { 12, 12, 5, 7, 1, 2, 1 } @@ -133,6 +134,8 @@ has_collided(Player *player, RoomMatrix *matrix, Vector2d direction) monster_hit(space->monster, hit); + animation_run(player->swordAnimation); + if (hit > 0) { gui_log("You hit %s for %u damage", space->monster->lclabel, hit); @@ -190,12 +193,41 @@ set_clip_for_direction(Player *player, Vector2d *direction) player->sprite->clip.y = 0; } +void +player_turn(Player *player, Vector2d *direction) +{ + set_clip_for_direction(player, direction); + + if (!vector2d_equals(*direction, VECTOR2D_NODIR)) + player->swordAnimation->sprite->pos = player->sprite->pos; + + if (vector2d_equals(*direction, VECTOR2D_UP)) { + player->swordAnimation->sprite->pos.y -= 32; + player->swordAnimation->sprite->angle = -90; + player->swordAnimation->sprite->flip = SDL_FLIP_NONE; + } else if (vector2d_equals(*direction, VECTOR2D_DOWN)) { + player->swordAnimation->sprite->pos.y += 32; + player->swordAnimation->sprite->angle = 90; + player->swordAnimation->sprite->flip = SDL_FLIP_NONE; + } else if (vector2d_equals(*direction, VECTOR2D_LEFT)) { + player->swordAnimation->sprite->pos.x -= 32; + player->swordAnimation->sprite->angle = 0; + player->swordAnimation->sprite->flip = SDL_FLIP_HORIZONTAL; + } else if (vector2d_equals(*direction, VECTOR2D_RIGHT)) { + player->swordAnimation->sprite->pos.x += 32; + player->swordAnimation->sprite->angle = 0; + player->swordAnimation->sprite->flip = SDL_FLIP_NONE; + } +} + static void move(Player *player, RoomMatrix *matrix, Vector2d direction) { - set_clip_for_direction(player, &direction); + player_turn(player, &direction); + player->sprite->pos.x += TILE_DIMENSION * (int) direction.x; player->sprite->pos.y += TILE_DIMENSION * (int) direction.y; + if (!has_collided(player, matrix, direction)) { player_step(player); } @@ -236,6 +268,11 @@ handle_next_move(UpdateData *data) static unsigned int step = 1; Player *player = data->player; + + // Don't move when projectiles are still moving + if (linkedlist_size(player->projectiles) > 0) + return; + RoomMatrix *matrix = data->matrix; Vector2d nextDir = read_direction_from(data->input); if (!vector2d_equals(nextDir, VECTOR2D_NODIR)) @@ -329,12 +366,34 @@ check_skill_trigger(UpdateData *data) return true; } +static void +build_sword_animation(Player *p, SDL_Renderer *renderer) +{ + animation_load_texture(p->swordAnimation, "Extras/SwordSwing.png", renderer); + animation_set_frames(p->swordAnimation, (AnimationClip[]) { + { 0, 0, 16, 16, 20 }, + { 16, 0, 16, 16, 20 }, + { 32, 0, 16, 16, 20 }, + { 48, 0, 16, 16, 20 }, + { 64, 0, 16, 16, 20 } + }); + + p->swordAnimation->loop = false; + p->swordAnimation->sprite->dim = GAME_DIMENSION; + p->swordAnimation->sprite->clip = (SDL_Rect) { 0, 0, 16, 16 }; + p->swordAnimation->sprite->rotationPoint = (SDL_Point) { 16, 16 }; +} + Player* player_create(class_t class, SDL_Renderer *renderer) { Player *player = malloc(sizeof(Player)); player->sprite = sprite_create(); +#ifdef DEBUG + player->daggers = 10; +#else player->daggers = 0; +#endif player->stat_data.total_steps = 0; player->stat_data.steps = 0; player->stat_data.hits = 0; @@ -347,6 +406,9 @@ player_create(class_t class, SDL_Renderer *renderer) player->state = ALIVE; player->projectiles = linkedlist_create(); player->animationTimer = timer_create(); + player->swordAnimation = animation_create(5); + + build_sword_animation(player, renderer); for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) { player->skills[i] = NULL; @@ -447,7 +509,12 @@ player_render(Player *player, Camera *cam) projectile_render(projectile->data, cam); projectile = projectile->next; } +} +void +player_render_toplayer(Player *player, Camera *camera) +{ + animation_render(player->swordAnimation, camera); } void @@ -502,6 +569,8 @@ void player_update(UpdateData *data) linkedlist_destroy(&player->projectiles); player->projectiles = remaining; + + animation_update(player->swordAnimation); } void @@ -510,6 +579,7 @@ player_destroy(Player *player) if (player->sprite) sprite_destroy(player->sprite); + animation_destroy(player->swordAnimation); timer_destroy(player->animationTimer); for (size_t i = 0; i < PLAYER_SKILL_COUNT; ++i) { diff --git a/src/player.h b/src/player.h index 352fc3d..fe5d18a 100644 --- a/src/player.h +++ b/src/player.h @@ -31,7 +31,8 @@ #define PLAYER_SKILL_COUNT 5 // Foward declare -struct UpdateData; +typedef struct UpdateData UpdateData; +typedef struct Animation Animation; typedef enum PlayerClass { ENGINEER, MAGE, PALADIN, ROGUE, WARRIOR } class_t; typedef enum PlayerState { ALIVE, DEAD, FALLING } state_t; @@ -64,6 +65,7 @@ typedef struct Player_t { state_t state; Skill *skills[PLAYER_SKILL_COUNT]; Timer *animationTimer; + Animation *swordAnimation; } Player; Player* @@ -90,6 +92,12 @@ player_update(struct UpdateData *); void player_render(Player*, Camera*); +void +player_render_toplayer(Player*, Camera*); + +void +player_turn(Player*, Vector2d *dir); + void player_destroy(Player*); diff --git a/src/projectile.c b/src/projectile.c index 320b8aa..3f43a56 100644 --- a/src/projectile.c +++ b/src/projectile.c @@ -100,6 +100,7 @@ projectile_update(Projectile *p, UpdateData *data) linkedlist_append(&data->map->items, item); } monster_hit(space->monster, dmg); + player_monster_kill_check(data->player, space->monster); } mixer_play_effect(SWORD_HIT); p->alive = false; diff --git a/src/roommatrix.c b/src/roommatrix.c index d63d383..a2f2ec4 100644 --- a/src/roommatrix.c +++ b/src/roommatrix.c @@ -25,6 +25,29 @@ #include "item.h" #include "update_data.h" +static void +roommatrix_reset(RoomMatrix *m) +{ + RoomSpace *space; + int i, j; + + for (i = 0; i < MAP_ROOM_WIDTH; ++i) { + for (j = 0; j < MAP_ROOM_HEIGHT; ++j) { + space = &m->spaces[i][j]; + space->occupied = false; + space->lethal = false; + space->lightsource = false; + space->light = 0; + space->monster = NULL; + space->player = NULL; + while (space->items != NULL) + linkedlist_pop(&space->items); + } + } + m->roomPos = (Position) { 0, 0 }; + m->playerRoomPos = (Position) { 1, 1 }; +} + RoomMatrix* roommatrix_create(void) { int i, j; @@ -242,29 +265,6 @@ roommatrix_render_lightmap(RoomMatrix *matrix, Camera *cam) } } -void -roommatrix_reset(RoomMatrix *m) -{ - RoomSpace *space; - int i, j; - - for (i = 0; i < MAP_ROOM_WIDTH; ++i) { - for (j = 0; j < MAP_ROOM_HEIGHT; ++j) { - space = &m->spaces[i][j]; - space->occupied = false; - space->lethal = false; - space->lightsource = false; - space->light = 0; - space->monster = NULL; - space->player = NULL; - while (space->items != NULL) - linkedlist_pop(&space->items); - } - } - m->roomPos = (Position) { 0, 0 }; - m->playerRoomPos = (Position) { 1, 1 }; -} - void roommatrix_destroy(RoomMatrix *m) { // Clear the list but don't destroy the items diff --git a/src/roommatrix.h b/src/roommatrix.h index 1cdbe22..e676c9b 100644 --- a/src/roommatrix.h +++ b/src/roommatrix.h @@ -26,7 +26,7 @@ #include "map_room_modifiers.h" #include "input.h" -typedef struct Sprite_t Sprite; +typedef struct Sprite Sprite; typedef struct Map_t Map; typedef struct Monster_t Monster; typedef struct Player_t Player; @@ -67,8 +67,6 @@ void roommatrix_render_mouse_square(RoomMatrix*, Camera*); void roommatrix_render_lightmap(RoomMatrix*, Camera*); -void roommatrix_reset(RoomMatrix*); - void roommatrix_destroy(RoomMatrix*); #endif // ROOMMATRIX_H_ diff --git a/src/skill.c b/src/skill.c index bfea534..3806c96 100644 --- a/src/skill.c +++ b/src/skill.c @@ -32,19 +32,7 @@ #include "projectile.h" #include "linkedlist.h" #include "item.h" - -static void -set_player_clip_for_direction(Player *player, Vector2d *direction) -{ - if (direction->y > 0) // Down - player->sprite->clip.y = 0; - else if (direction->y < 0) // Up - player->sprite->clip.y = 48; - else if (direction->x < 0) // Left - player->sprite->clip.y = 16; - else if (direction->x > 0) // Right - player->sprite->clip.y = 32; -} +#include "animation.h" static Skill * create_default(const char *s_label, Sprite *s) @@ -73,12 +61,13 @@ skill_use_flurry(Skill *skill, SkillData *data) targetPos.x += (int) data->direction.x; targetPos.y += (int) data->direction.y; - set_player_clip_for_direction(data->player, &data->direction); + player_turn(data->player, &data->direction); if (!position_in_roommatrix(&targetPos)) { return false; } + animation_run(data->player->swordAnimation); Monster *monster = data->matrix->spaces[targetPos.x][targetPos.y].monster; mixer_play_effect(TRIPPLE_SWING); if (monster) { @@ -160,7 +149,7 @@ skill_throw_dagger(Skill *skill, SkillData *data) p->sprite->angle = -270; } - set_player_clip_for_direction(data->player, &data->direction); + player_turn(data->player, &data->direction); mixer_play_effect(SWOOSH); p->sprite->pos = data->player->sprite->pos; @@ -263,7 +252,7 @@ skill_charge(Skill *skill, SkillData *data) player->sprite->pos.x += (steps * TILE_DIMENSION) * (int) data->direction.x; player->sprite->pos.y += (steps * TILE_DIMENSION) * (int) data->direction.y; Position playerDestinationPos = player->sprite->pos; - set_player_clip_for_direction(data->player, &data->direction); + player_turn(data->player, &data->direction); // Add motion particles bool horizontal = data->direction.x != 0; @@ -294,6 +283,7 @@ skill_charge(Skill *skill, SkillData *data) data->player->stat_data.hits += 1; } monster_hit(monster, dmg); + player_monster_kill_check(data->player, monster); } return true; diff --git a/src/skillbar.c b/src/skillbar.c index 7c2fcc6..ea20d73 100644 --- a/src/skillbar.c +++ b/src/skillbar.c @@ -222,6 +222,10 @@ render_skill_sparkles(SkillBar *bar, Player *player) return; } + if (player->stats.lvl == 1) { + return; + } + Position pos = { 0, GAME_VIEW_HEIGHT }; Dimension dim = { 32, 32 }; for (int i = 0; i < PLAYER_SKILL_COUNT; ++i) { diff --git a/src/sprite.c b/src/sprite.c index 3ba49f9..e1a4040 100644 --- a/src/sprite.c +++ b/src/sprite.c @@ -51,7 +51,7 @@ sprite_create(void) void sprite_load_texture(Sprite *sprite, - char *path, + const char *path, int index, SDL_Renderer *renderer) { @@ -68,7 +68,7 @@ sprite_load_texture(Sprite *sprite, sprite->destroyTextures = true; } -void sprite_load_text_texture(Sprite *sprite, char * path, int index, int size, int outline) +void sprite_load_text_texture(Sprite *sprite, const char * path, int index, int size, int outline) { if (index > 1) fatal("in sprite_load_texture() index out of bounds"); @@ -122,7 +122,7 @@ sprite_render(Sprite *s, Camera *cam) cameraPos.x, cameraPos.y, s->dim.width, s->dim.height }; - if ((s->clip.w && s->clip.h) || s->angle != 0 || s->flip != SDL_FLIP_NONE) { + if (s->angle != 0 || s->flip != SDL_FLIP_NONE) { texture_render_clip_ex(s->textures[s->texture_index], &box, &s->clip, diff --git a/src/sprite.h b/src/sprite.h index bbea9ad..38b0c56 100644 --- a/src/sprite.h +++ b/src/sprite.h @@ -27,7 +27,7 @@ #include "roommatrix.h" #include "timer.h" -typedef struct Sprite_t { +typedef struct Sprite { Texture* textures[2]; SDL_Rect clip; bool destroyTextures; @@ -46,9 +46,9 @@ typedef struct Sprite_t { Sprite* sprite_create(void); -void sprite_load_texture(Sprite *, char *path, int index, SDL_Renderer *); +void sprite_load_texture(Sprite *, const char *path, int index, SDL_Renderer *); -void sprite_load_text_texture(Sprite *, char *path, int index, int size, int outline); +void sprite_load_text_texture(Sprite *, const char *path, int index, int size, int outline); void sprite_set_texture(Sprite *, Texture *, int index); diff --git a/src/timer.h b/src/timer.h index 98d2e11..86c45c1 100644 --- a/src/timer.h +++ b/src/timer.h @@ -21,7 +21,7 @@ #include -typedef struct { +typedef struct Timer { unsigned int startTime; } Timer;