1. Euphoria Physics

Hi all, With the help of chatGpt. I got some Euphoria physics going with a simple vehicle.

https://github.com/gAndy50/EuRayLib5 - Raylib wrapper

https://github.com/ghaberek/libffi-euphoria - FFI

include std/ffi.e 
include raylib.e 
 
constant SCREEN_WIDTH = 800 
constant SCREEN_HEIGHT = 600 
constant GROUND_Y = 500 
constant TIME_STEP = 1.0 / 60.0 
 
-- Car body 
constant CAR_WIDTH = 100 
constant CAR_HEIGHT = 30 
 
-- Suspension 
constant SPRING_LENGTH = 20.0 
constant SPRING_K = 200.0        -- Spring stiffness 
constant DAMPING = 10.0 
 
-- Gravity 
constant GRAVITY = 980.0 
 
-- Wheel properties 
constant WHEEL_RADIUS = 15 
 
object car_pos = {400.0, 300.0}  -- Starting position of the car 
object car_vel = {0.0, 0.0}      -- Starting velocity (no initial movement) 
 
object wheel_pos = { 
    {car_pos[1] - 30, car_pos[2] + SPRING_LENGTH}, 
    {car_pos[1] + 30, car_pos[2] + SPRING_LENGTH} 
} 
 
object wheel_vel = { 
    {0.0, 0.0}, 
    {0.0, 0.0} 
} 
 
object wheel_angle = {0.0, 0.0}  -- Initial wheel rotation angle 
 
procedure update_wheel(integer i) 
    -- Set the horizontal position of the wheel to follow the car's horizontal position 
    atom anchor_x 
    if i = 1 then 
        anchor_x = car_pos[1] - 30  -- Left wheel 
    else 
        anchor_x = car_pos[1] + 30  -- Right wheel 
    end if 
 
    -- The vertical position is still influenced by the spring forces 
    atom anchor_y = car_pos[2] 
 
    -- Spring force calculations (same as before) 
    atom dx = wheel_pos[i][1] - anchor_x 
    atom dy = wheel_pos[i][2] - anchor_y 
 
    atom length = sqrt(power(dx, 2) + power(dy, 2)) 
    atom stretch = length - SPRING_LENGTH 
 
    -- Normalize spring direction 
    atom nx = dx / length 
    atom ny = dy / length 
 
    -- Relative velocity along spring direction 
    atom rel_vx = wheel_vel[i][1] - car_vel[1] 
    atom rel_vy = wheel_vel[i][2] - car_vel[2] 
    atom rel_dot = rel_vx * nx + rel_vy * ny 
 
    -- Spring force (Hooke's Law + damping) 
    atom force = -SPRING_K * stretch - DAMPING * rel_dot 
 
    -- Apply force to wheel (simple mass=1) 
    wheel_vel[i][1] += -nx * force * TIME_STEP 
    wheel_vel[i][2] += -ny * force * TIME_STEP + GRAVITY * TIME_STEP 
 
    -- Update wheel position 
    wheel_pos[i][1] = anchor_x  -- Ensure horizontal position is anchored to the car 
    wheel_pos[i][2] += wheel_vel[i][2] * TIME_STEP 
 
    -- Ground collision 
    if wheel_pos[i][2] >= GROUND_Y then 
        wheel_pos[i][2] = GROUND_Y 
        if wheel_vel[i][2] > 0 then 
            wheel_vel[i][2] = 0 
        end if 
    end if 
end procedure 
 
procedure update_car_body() 
    car_pos[2] = (wheel_pos[1][2] + wheel_pos[2][2]) / 2 - SPRING_LENGTH 
    -- Update the car's horizontal position based on velocity 
    car_pos[1] += car_vel[1] * TIME_STEP 
end procedure 
 
procedure draw_wheel(integer i) 
    -- Calculate the wheel rotation angle based on car velocity 
    -- The wheel rotates based on horizontal velocity of the car (car_vel[1]) 
    wheel_angle[i] += car_vel[1] / WHEEL_RADIUS * TIME_STEP 
     
    -- Keep angle within a full circle range 
    if wheel_angle[i] > 2 * 3.14159 then 
        wheel_angle[i] -= 2 * 3.14159 
    end if 
 
    -- Draw the wheel (rotate using wheel_angle) 
    atom wheel_x = wheel_pos[i][1] 
    atom wheel_y = wheel_pos[i][2] 
 
    -- Draw the wheel as a full circle 
    DrawCircle(wheel_x, wheel_y, WHEEL_RADIUS, BLACK) 
 
    -- Draw rotation indicator (simulating rotation) 
    atom angle = wheel_angle[i] 
    atom line_x = wheel_x + WHEEL_RADIUS * cos(angle) 
    atom line_y = wheel_y + WHEEL_RADIUS * sin(angle) 
 
    DrawLine(wheel_x, wheel_y, line_x, line_y, RED)  -- A line to indicate rotation direction 
end procedure 
 
procedure draw_scene() 
    ClearBackground(RAYWHITE) 
 
    -- Draw ground 
    DrawLine(0, GROUND_Y, SCREEN_WIDTH, GROUND_Y, DARKGREEN) 
 
    -- Draw car body 
    DrawRectangle(car_pos[1] - CAR_WIDTH / 2, car_pos[2] - CAR_HEIGHT / 2, CAR_WIDTH, CAR_HEIGHT, RED) 
 
    -- Draw wheels 
    for i = 1 to 2 do 
        draw_wheel(i) 
 
        -- Draw spring line 
        atom anchor_x 
        if i = 1 then 
            anchor_x = car_pos[1] - 30 
        else 
            anchor_x = car_pos[1] + 30 
        end if 
        DrawLine(anchor_x, car_pos[2], wheel_pos[i][1], wheel_pos[i][2], GRAY) 
    end for 
end procedure 
 
InitWindow(SCREEN_WIDTH, SCREEN_HEIGHT, "2D Car Suspension in Euphoria + raylib") 
SetTargetFPS(60) 
 
while not WindowShouldClose() do 
    -- Update wheels 
    update_wheel(1) 
    update_wheel(2) 
 
    -- Update car body height from wheels 
    update_car_body() 
 
    -- Handle user input for car movement 
    if IsKeyDown(KEY_RIGHT) then 
        car_vel[1] += 100 * TIME_STEP  -- Apply force to the car in the right direction 
    end if 
 
    if IsKeyDown(KEY_LEFT) then 
        car_vel[1] -= 100 * TIME_STEP  -- Apply force to the car in the left direction 
    end if 
 
    -- Draw the scene 
    BeginDrawing() 
    draw_scene() 
    DrawText(TextFormat("Wheel: %d",wheel_pos[1]),10,10,20,YELLOW) 
    DrawText(TextFormat("Wheel: %d",wheel_pos[2]),10,40,20,YELLOW) 
    EndDrawing() 
end while 
 
CloseWindow() 

Demo in action [https://youtube.com/shorts/hxutbr6BM_w?feature=share]

new topic     » topic index » view message » categorize

2. Re: Euphoria Physics

Is that any good? Got any screenshots/videos of what it should look like?
Mind just goes splat into the ground, no "springiness" at all.
I cannot see anything, for instance, that sets car_vel[2] non-0

new topic     » goto parent     » topic index » view message » categorize

3. Re: Euphoria Physics

petelomax said...

Is that any good? Got any screenshots/videos of what it should look like?
Mind just goes splat into the ground, no "springiness" at all.
I cannot see anything, for instance, that sets car_vel[2] non-0

I've added a short video showing its demonstration.

Screenshot: [https://i.imgur.com/37m5DxI.png]

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu