Merge branch 'master' into dev
This commit is contained in:
commit
2aee3600e6
2
.vimrc
2
.vimrc
|
@ -1,7 +1,7 @@
|
|||
nnoremap <F1> :Make<cr>
|
||||
nnoremap <F2> :Make lint test<cr>
|
||||
nnoremap <F3> :Termdebug _build/breakhack<cr>
|
||||
nnoremap <F4> :ter _build/breakhack<cr>
|
||||
nnoremap <F4> :ter ++close ./_build/breakhack<cr>
|
||||
|
||||
packadd termdebug
|
||||
let g:termdebug_wide = 1
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
<!--[![Coverity Scan](https://scan.coverity.com/projects/15218/badge.svg)](https://scan.coverity.com/projects/liquidityc-breakhack)-->
|
||||
|
||||
Something in the ways of NETHACK
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 297 B |
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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);
|
||||
}
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
* BreakHack - A dungeone crawler RPG
|
||||
* Copyright (C) 2018 Linus Probert <linus.probert@gmail.com>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _ANIMATION_H
|
||||
#define _ANIMATION_H
|
||||
|
||||
#include <SDL.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
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
|
||||
|
||||
|
|
@ -25,7 +25,7 @@
|
|||
#include "timer.h"
|
||||
#include "vector2d.h"
|
||||
|
||||
typedef struct {
|
||||
typedef struct Camera {
|
||||
Position pos;
|
||||
Position basePos;
|
||||
Vector2d velocity;
|
||||
|
|
|
@ -43,5 +43,4 @@ void linkedlist_destroy(LinkedList **head);
|
|||
|
||||
unsigned int linkedlist_size(LinkedList *head);
|
||||
|
||||
|
||||
#endif // LINKEDLIST_H_
|
||||
|
|
57
src/main.c
57
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();
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@
|
|||
#include "mixer.h"
|
||||
#include "collisions.h"
|
||||
|
||||
typedef struct MenuItems_t {
|
||||
typedef struct MenuItems {
|
||||
Sprite *sprite;
|
||||
Sprite *hsprite;
|
||||
GuiButton *button;
|
||||
|
|
|
@ -66,6 +66,10 @@ monster_state_change(Monster *m, StateType newState)
|
|||
|
||||
m->state.current = newState;
|
||||
m->state.stepsSinceChange = 0;
|
||||
|
||||
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;
|
||||
|
@ -271,7 +275,7 @@ monster_agressive_walk(Monster *m, RoomMatrix *rm)
|
|||
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,10 +293,18 @@ 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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
72
src/player.c
72
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) {
|
||||
|
|
10
src/player.h
10
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*);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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_
|
||||
|
|
22
src/skill.c
22
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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef struct {
|
||||
typedef struct Timer {
|
||||
unsigned int startTime;
|
||||
} Timer;
|
||||
|
||||
|
|
Loading…
Reference in New Issue