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

Very much WIP using some of the graphical style/themes from Mint in a Vampire Survivors style game.

WIP has:

  • 2 characters with different modifiers
  • 6 weapons and 1 passive item. weapons and passives have level upgrade modifiers
  • A wave spawner (but it spawns the same stuff every wave - need more mob types)
  • Boss mobs drop a chest that will drop a random upgrade to an item in your inventory
  • Standard mobs drop xp, hitting the target xp for the level triggers a shop where you are offered 3 items (with some weighting towards items you already own)

"O" button does everything.

TODO:

  • refactor for performance, I think I can improve collision handling
  • a proper map, thinking an infinite map like vampire survivors
  • scaling of mobs with XP
  • more items
  • more enemy types
  • probably refactor how I am doing classes, it's getting messy.
  • bugs, probably lots of them
  • everything else

Cart #diphwezu-1 | 2024-05-02 | Embed ▽ | No License
4

P#147772 2024-05-02 13:30 ( Edited 2024-05-02 14:01)

[ :: Read More :: ]

Hello, I have this code that circles an object around the player position.

It works well if the player stands still, but if the player moves the trajectory of the object goes a bit wonky. it sort of stops, or looks like it wants to go in the other direction for a bit.

How can I make it smoothly rotate around the player?

    local player = self.game_context.player
    local orbit_radius = 40  -- Distance from player to orbiting projectile
    local orbit_speed = self.speed  -- Normalized speed of orbit; consider this as fraction of a circle per frame

    for p in all(self.projectiles) do
        p.angle += orbit_speed
        if (p.angle > 360) p.angle = 0
        p.x = player.x + (player.attributes.w / 2) + orbit_radius * cos(p.angle/360)
        p.y = player.y + (player.attributes.h / 2) + orbit_radius * sin(p.angle/360)
        -- Handle projectile duration and collision
        p.duration -= 1 
    end     
P#147652 2024-04-30 15:18

[ :: Read More :: ]

Hello,

I feel like I am being a bit thick this morning.

I have a 128 x 128 sprite sheet as a .png.

I've tried importpng and the pictron exporter from asesprite. both exhibit the same behaviour, when I paste from the clipboard the whole image fills sprite 0 and sets its size to 128 x 128, I'm expecting the image to start at sprite 0 and fill outwards. Am I missing something obvious?

thanks in advance

P#147541 2024-04-29 09:35 ( Edited 2024-04-29 09:35)

[ :: 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)