Log In  
Follow
supercurses
[ :: Read More :: ]

Hello, considering the following:

Trying to remake Vampire Survivors and a fun project
I have a character class
Characters have effects that are applied to a target. In this example my target = player
I have a character that is an instance of that class. Let's call him "Antonio"
I have a "run", Antonio is copied into run.player
I set player to be run.player

My problem is that I have to initiate the character class and Antonio before I create "player". But player is not yet created so player referenced on the character class is nil.

I hope this makes sense, I have a workaround but it feels clunky and I'm wondering if there are other solutions.

Here is my code before the workaround:

character = {}
character.__index = character
function character:new(name)
    local o = setmetatable({}, character)
    o.name = name
    o.x = 0
    o.y = 0
    o.sp_scale = 1
    o.w = 16
    o.h = 16
    o.effects = effects
    o.original_invincibility_frames = 10
    o.invincibility_frames = 0
    o.max_health = 100
    o.health = 20
    o.recovery = 0
    o.armor = 0
    o.move_speed = 1
    o.might = 1
    o.weapon_projectile_speed = 0
    o.weapon_duration = 0
    o.weapon_area = 0
    o.weapon_cooldown = 0
    o.weapon_projectiles_amount = 0
    o.revival = 0
    o.magnet = 0
    o.luck = 0
    o.growth = 0
    o.greed = 0
    o.curse = 0
    o.reroll = 0
    o.skip = 0
    o.banish = 0
    return o
end

function character:set_effects(effects)
    self.effects = effects
end

function character:apply_effects(level)

    local effects = self.effects
    for _, effect in pairs(effects) do
        if level % effect.level_increment == 0 and 
            level <= effect.max_level_increment then 
            local target = effect.target    
            if effect.mode == "percent" then
                target[effect.stat] += (target[effect.stat] or 0) * effect.value
            else
                target[effect.stat] = (target[effect.stat] or 0) + effect.value
            end
        end

    end
end

antonio = character:new("antonio")
antonio.recovery = 0.5
antonio:set_effects( {

                    {   description="Gains 10% Might every 2 Levels",  
                        stat = "might", 
                        value = 1,
                        target = player, -- here is the problem, player doesn't exist
                        level_increment = 2,
                        max_level_increment = 10,
                        mode = "percent"
                    },
                    {   description="Gains 0.5 Recovery every 1 level", 

                        stat = "recovery", 
                        value = 0.5,
                        target = player,
                        level_increment = 1,
                        max_level_increment = 5
                    }

                }

)

function _init()
    t = 0
    run = {}
    run.player = {}
    run.level = 1
    add(run.player, deepcopy(antonio))

    player = run.player[1]

end

function _update()

    if t % 60 == 0 then player.health += player.recovery end 
    if btnp(4) then
        run.level += 1
        player:apply_effects(run.level)
    end
    t += 1
end

function _draw()
    local y = 0
    cls(0)
    for entry in all(run.player) do
        for k, v in pairs(entry) do
            if type(v) == "number" then
                print(k..":"..v, 0, y)
                y += 8
            end
        end
    end
    local y = 0
    print("Level: "..run.level, 240, y)

end

function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, getmetatable(orig))
    else -- for numbers, strings, booleans, etc
        copy = orig
    end
    return copy

end

And here is my code with the workaround, in short, once player is created I go and apply player as the target of the effects: player:update_effects_target(player)

character = {}
character.__index = character
function character:new(name)
    local o = setmetatable({}, character)
    o.name = name
    o.x = 0
    o.y = 0
    o.sp_scale = 1
    o.w = 16
    o.h = 16
    o.effects = effects
    o.original_invincibility_frames = 10
    o.invincibility_frames = 0
    o.max_health = 100
    o.health = 20
    o.recovery = 0
    o.armor = 0
    o.move_speed = 1
    o.might = 1
    o.weapon_projectile_speed = 0
    o.weapon_duration = 0
    o.weapon_area = 0
    o.weapon_cooldown = 0
    o.weapon_projectiles_amount = 0
    o.revival = 0
    o.magnet = 0
    o.luck = 0
    o.growth = 0
    o.greed = 0
    o.curse = 0
    o.reroll = 0
    o.skip = 0
    o.banish = 0
    return o
end

function character:set_effects(effects)
    self.effects = effects
end

function character:update_effects_target(target)
    for _, effect in pairs(self.effects) do
        effect.target = target
    end
end

function character:apply_effects(level)

    local effects = self.effects
    for _, effect in pairs(effects) do
        if level % effect.level_increment == 0 and 
            level <= effect.max_level_increment then 
            local target = effect.target    
            if effect.mode == "percent" then
                target[effect.stat] += (target[effect.stat] or 0) * effect.value
            else
                target[effect.stat] = (target[effect.stat] or 0) + effect.value
            end
        end

    end
end

antonio = character:new("antonio")
antonio.recovery = 0.5
antonio:set_effects( {

                    {   description="Gains 10% Might every 2 Levels",  
                        stat = "might", 
                        value = 1,
                        target = player, -- here is the problem, player doesn't exist
                        level_increment = 2,
                        max_level_increment = 10,
                        mode = "percent"
                    },
                    {   description="Gains 0.5 Recovery every 1 level", 

                        stat = "recovery", 
                        value = 0.5,
                        target = player,
                        level_increment = 1,
                        max_level_increment = 5
                    }

                }

)

function _init()
    t = 0
    run = {}
    run.player = {}
    run.level = 1
    add(run.player, deepcopy(antonio))

    player = run.player[1]
    player:update_effects_target(player)
end

function _update()

    if t % 60 == 0 then player.health += player.recovery end 
    if btnp(4) then
        run.level += 1
        player:apply_effects(run.level)
    end
    t += 1
end

function _draw()
    local y = 0
    cls(0)
    for entry in all(run.player) do
        for k, v in pairs(entry) do
            if type(v) == "number" then
                print(k..":"..v, 0, y)
                y += 8
            end
        end
    end
    local y = 0
    print("Level: "..run.level, 240, y)

end

function deepcopy(orig)
    local orig_type = type(orig)
    local copy
    if orig_type == 'table' then
        copy = {}
        for orig_key, orig_value in next, orig, nil do
            copy[deepcopy(orig_key)] = deepcopy(orig_value)
        end
        setmetatable(copy, getmetatable(orig))
    else -- for numbers, strings, booleans, etc
        copy = orig
    end
    return copy

end
P#147242 2024-04-24 10:32 ( Edited 2024-04-24 10:32)

[ :: Read More :: ]

Hello,

For fun, I'm building a Vampire Survivors style game. There will be a lot of mobs on screen, so I've built a grid partitioning system and each weapon only checks for collisions with mobs nearby.

The grid size is 30, so that's a 16 x 9 grid.

My question is this, currently, I'm initialising the grid on every frame and re-populating all the mob positions into their grids.

Should I move to initialising just once and updating mob positions in the grid on every frame? I'm not sure whether that will actually be quicker because I will have to delete the mob from one grid position and add it to another.

Also, that seems hard to implement :-)

Thanks in advance

Russ

P#146831 2024-04-17 15:45

[ :: Read More :: ]

Cart #rikazogoye-3 | 2023-03-11 | Code ▽ | Embed ▽ | License: CC4-BY-NC-SA
1

Knuckle Dice v1.3

Knuckle Dice is an attempt to recreate Knuckle Bones from Cult of the Lamb. This is my first programming project ever so there's no AI yet - it's two player only to begin with.

In the future I will try to add:

  • CPU AI (DONE)
  • I want to experiment with perfect information. In other words, remove the randomness and tell the player exactly what the opponent is about to play.

Controls

  • z to start/restart
  • x to play a dice

Rules/Game Logic

  • Maximum 3 dice in one column
  • Playing a die in a column that matches dice in the opposing player's column removes all instances of that dice
  • When nine dice are played by either player the game ends

Scoring

  • You receive points equivalent to the die played multiplied by the number of instances of that dice. (e.g a 5 played twice in one column will give you twenty points - 2*(5+5)
  • The player with the most points wins

v1.1 Updates

  • Changed GFX to more of a 1bit style

v1.3 Updates

  • Now it's a single player game with some rudimentary AI for P2
P#126787 2023-03-08 16:14 ( Edited 2023-03-11 12:58)