Log In  
Follow
supercurses

Hello,

I have a feeling I don't fully understand vectors. I am thinking of the optimal way to handle the updating of a large number of entities for something like a Vampire Survivors game. Right now, in my testing, parallel arrays appears to have the lowest impact on CPU. 1000 mobs move towards the player and cpu is 0.601, metatables go up to 0.823

I tried vectors this morning and my cpu stat is 1.4.

Vectors are a bit new to me and I'm wondering if I going about this the right way.

function _init()
	mobs={}
	player={}
	player.v = vec(240, 130)
	for i=1, 1000 do
		local spawn_radius = max(470, 270) / 2 + 50
		local player_x, player_y = player.v:get(0, 2)
		local spawn_x = player_x
		local spawn_y = player_y
		local angle = rnd(1)
		local x = spawn_x + spawn_radius * cos(angle)
		local y = spawn_y + spawn_radius * sin(angle)

		v = vec(x, y)
		add(mobs,{v=v,spd=rnd(0.5)})
	end

end

function _update()

	for mob in all(mobs) do
		-- Calculate direction vector (from mob to player)
		local direction = vec(0, 0)

		-- Get mob and player positions
		local mob_x, mob_y = mob.v:get(0, 2)
		local player_x, player_y = player.v:get(0, 2)

		-- Create direction vector
		direction = vec(player_x - mob_x, player_y - mob_y)

		-- Normalize the direction (make it length 1)
		local mag = direction:magnitude()
		if mag > 0 then
			direction = direction:div(mag)

			mob.v = mob.v:add(direction:mul(mob.spd))
		end
	end
end

function _draw()
    cls()
    for mob in all(mobs) do
        local x, y = mob.v:get(0, 2)
        spr(1, x, y)
    end
    print(stat(1), 0, 0, 8)
end
1
6 comments



Hello,

I am simulating a ball being dragged around by a player. I'd like to create some animation to simulate that the ball is rotating (top-down view). I am trying to do that with a light source on top of the ball but I can't quite get it working correctly.

Looking for advice or some pointers to good tutorials on this subject.

Thanks in advance

function _init()
	player = {x=64, y=64}

end

function _update()
 local move_x, move_y = 0, 0
 if btn(0) then move_x = -1 end
 if btn(1) then move_x = 1 end
 if btn(2) then move_y = -1 end
 if btn(3) then move_y = 1 end

 -- update player position and animation
 if move_x != 0 or move_y != 0 then
     player.x += move_x
     player.y += move_y 
	end
	update_ball()

end

function _draw()
	cls()
	rectfill(player.x,
		player.y,
		player.x+8,
		player.y+8,
		8)
	draw_ball()

end

--ball

ball = {x=80, y=80, vx=0, vy=0, length=24, friction=0.9, mass=5, pull_force=0.2}

ball.hitbox = {2,2,6,6}
ball.name = "ball"
ball.radius = 5

-- in ball initialization
ball.light_pos = {x = ball.x, y = ball.y}

function distance(x1, y1, x2, y2)
    return sqrt((x2-x1)^2 + (y2-y1)^2)
end

function update_ball()
    local dx = ball.x - player.x
    local dy = ball.y - player.y 
    local dist = distance(ball.x, ball.y, player.x, player.y)

    if dist > ball.length then
        local angle = atan2(dx, dy)
        local pull_strength = (dist - ball.length) * ball.pull_force

        ball.vx -= cos(angle) * pull_strength
        ball.vy -= sin(angle) * pull_strength
    end
    ball.vx *= ball.friction
    ball.vy *= ball.friction
    ball.x += ball.vx
    ball.y += ball.vy

    if ball.vx != 0 or ball.vy != 0 then
        local move_dir_x = ball.vx > 0 and 1 or (ball.vx < 0 and -1 or 0)
        local move_dir_y = ball.vy > 0 and 1 or (ball.vy < 0 and -1 or 0)

        ball.light_pos.x += move_dir_x * 0.5
        ball.light_pos.y += move_dir_y * 0.5

        -- check if light has reached ball edge
        local light_dist = distance(ball.x, ball.y, ball.light_pos.x, ball.light_pos.y)

        if light_dist >= ball.radius+1 then
             -- move light along the direction of movement
             ball.rolled_under = true
            ball.roll_under_timer = ball.roll_under_frames

            -- reposition light on opposite side of ball and continue moving
            ball.light_pos.x = ball.x - move_dir_x * ball.radius
            ball.light_pos.y = ball.y - move_dir_y * ball.radius

            -- immediately continue moving in the same direction
            ball.light_pos.x += move_dir_x * 0.5
            ball.light_pos.y += move_dir_y * 0.5
        end

    end

end

function draw_ball()
    line(player.x+4, player.y+4, ball.x, ball.y, 13)
    circfill(ball.x, ball.y, 5, 1)

    -- light spot
    circfill(ball.light_pos.x, ball.light_pos.y, 1, 7)

end
4 comments



In the following code, everything works apart from table.sort(). How would I know that?

Also, the only keyword highlighted in the code editor is "sub"

s = "hello world"
i, j = string.find(s, "hello")
print(i..":"..j)
print(string.sub(s, i, j))
print(string.find(s, "world"))

local t = {}
table.insert(t, 1)
table.insert(t, 24)
for i=1, #t do
	print(t[i])
end
table.sort(t)
2
4 comments



Hello,

I'm a beginner programmer, trying to figure out good practice. To be honest, I get a lot of joy out of refactoring code even though I know it's more important to create something of value. Seems to give my brain comfort.

I've been creating a card game and realised that one of my challenges is that I have a card object that has some game logic associated with it but I'm also mixing up a bunch of presentation information on that card. It's getting messy.

Which got me thinking about trying to separate concerns. Wondering what the community's view is on an approach like below?

The general idea here is that a card needs to know nothing about its presentation (but is linked to its presentation). It's a bidirectional link, a card_view is related to its card.

Obviously, in a game where there are not a lot of objects, this might be overkill.

function _init()
	renderer = Renderer:new()
	animator = Animator:new()
	deck = {}
	x_offset, y_offset, i = 0, 0, 0

[ [size=16][color=#ffaabb] [ Continue Reading.. ] [/color][/size] ](/bbs/?pid=153542#p)
0 comments



Hello,

I've been working on trying to produce a randomly generated map like in Slay the Spire.

I used the rules documented here to generate the map:

https://steamcommunity.com/sharedfiles/filedetails/?id=2830078257

(not convinced these are the whole rules but it's good enough for now)

The map is a 7 x 15 grid.
6 paths are drawn through the grid, the first two paths must be at different starting points, others are random (which gives the branching effect)
Events are placed on the grid as per the weightings specified.
Some rules are obeyed to prevent certain events from appearing in certain places (for example, 2 rest sites in a row are not allowed)
I added some jittering to give the map rendering a more organic look.

Controls

1) You can scroll up and down the map with the up and down keys.
2) Hit left and right to select an originating path. Press X to lock in the selection.
3) Press up to move up that selected path.
4) While you have a path selected, press left and right to move between valid branches of the path.

[ Continue Reading.. ]

8 comments



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-2 | 2024-05-20 | Embed ▽ | No License
4

[ Continue Reading.. ]

4
4 comments



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		
2 comments



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

2 comments



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

[ [size=16][color=#ffaabb] [ Continue Reading.. ] [/color][/size] ](/bbs/?pid=147242#p)
2 comments



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

1
1 comment



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
1
3 comments