NaaLaa
Rotated and scaled image drawing - Printable Version

+- NaaLaa (https://www.naalaa.com/forum)
+-- Forum: NaaLaa (https://www.naalaa.com/forum/forum-1.html)
+--- Forum: NaaLaa 7 Code (https://www.naalaa.com/forum/forum-4.html)
+--- Thread: Rotated and scaled image drawing (/thread-92.html)

Pages: 1 2 3


RE: Rotated and scaled image drawing - Marcus - 03-14-2024

I managed to do some 3D related things last week, stuff that can help make the kind of games that 1micha.elok is working on. The s3d library used here is far from ready, fast or useful. But I think I'll stick to the 3D path for a while and see what's possible.

Edit You might need to install n7 version 24.03.10 for this to compile and run this without any crashes ...


RE: Rotated and scaled image drawing - johnno56 - 03-15-2024

Already installed the new n7. Test program runs very smoothly without errors... I see that there are stilll no aliens to shoot... Moo Ha Ha Ha...

Hope that you have recovered?


RE: Rotated and scaled image drawing - 1micha.elok - 03-15-2024

(03-14-2024, 07:00 PM)Marcus Wrote: ... The s3d library used here ....
You might need to install n7 version 24.03.10 ...

TEST DRIVE
Three different themes on the racing game : winter, tropical, night
           
click the image to zoom in

Control :
 - movement            : LEFT, RIGHT
 - speed                   : UP, DOWN
 - stop                     : SPACE
 - theme selection     : 1 = winter, 2 = tropical, 3 = night
 - quit                      : ESC
 - music,sound off     : S

 Acknowledgements :
 This game would not be possible without
 1. Marcus for New Libraries
    -s3d.n7 library, required version N7_240310
    -racing.n7, example how to use s3d library
    -SquareWave(), sfx.n7 library
    -DrawImageTransformed()
 2. Johnno for every valuable suggestion
 3. Sprites
    - https://pngtree.com/so/steering-wheel
    - https://opengameart.org/content/25d-racing-resources
 4. Music and Acceleration Sound https://pixabay.com

Code:
'========================================
' TEST DRIVE
'
' Control :
' - movement        : LEFT, RIGHT
' - speed           : UP, DOWN
' - stop            : SPACE
' - theme selection : 1 = winter
'                     2 = tropical
'                     3 = night
' - quit            : ESC
' - music,sound off : S
'
' Note :
' This game is just a proof of concept.
' There are still some tasks left opened.
' (collision, road track, finish line, etc.)
'
' Acknowledgements :
' This game would not be possible without
' 1. Marcus for New Libraries
'    -s3d.n7 library, required version N7_240310
'    -racing.n7, example how to use s3d library
'    -SquareWave(), sfx.n7 library
'    -DrawImageTransformed()
' 2. Johnno for every valuable suggestion
' 3. Sprites
'    - https://pngtree.com/so/steering-wheel
'    - https://opengameart.org/content/25d-racing-resources
' 4. Music and Acceleration Sound https://pixabay.com
'==============================================

'-----------------
' INITIALIZATION
'-----------------
' Marcus : A library that I'm working on, not finished at all, don't use it!
' Micha  : Oops...sorry, I use it :)
include "assets/s3d.n7"
S3D_SetView(primary, rad(90), 0.1, 20)' Set up 3d view.
S3D_SetDirectMode(true) 'true = draw from back to front manually
include "assets/soundtune.n7"
include "assets/transform.n7"

#win32
'#dbg
set window "TEST DRIVE", 320, 240, false, 2
set redraw off

'color definition
white         = [255,255,255]
white_alpha   = [255,255,255,255]
gray          = [218,218,218]
green         = [0,200,0]
black         = [50,50,50]
red           = [255,0,0]

'road
road = []
for z = 0 to 999  road[z] = [x: sin(z*0.05)*6, y: sin(z*0.1)*3]
road[1].img     = loadimage("assets/road_winter.png")
road[2].img     = loadimage("assets/road_beach.png")
road[3].img     = loadimage("assets/road_city.png")
road.width_     = width(road[1].img)
road.height_    = height(road[1].img)

'decorations
land        = []
land[1]     = gray
land[2]     = green
land[3]     = black
tree        = []
tree[1]     = loadimage("assets/tree_winter.png")
tree[2]     = loadimage("assets/tree_palm.png")
tree[3]     = loadimage("assets/house.png")
tunnel      = []
tunnel[1]   = loadimage("assets/tunnel_winter.png")
tunnel[2]   = loadimage("assets/tunnel_green.png")
tunnel[3]   = loadimage("assets/tunnel_city.png")
back        = []
back[1]     = loadimage("assets/sky_winter2.png")
back[2]     = loadimage("assets/sky_tropical.png")
back[3]     = loadimage("assets/sky_night.png")
back.music_ = loadmusic("assets/rock.wav")

'player
player = []
player.z = 0.0
player.x = 0
player.y = -1
player.speed = 0
player.gas = loadsound("assets/acceleration.wav")
player.img = loadimage("assets/wheel.png")
player.wheel = 0

'misc initial values
projected = dim(4) ' Don't want to spawn too many tables in a game loop, reused for calculations.
lastTick = clock()
theme  = 1 ;t1 = 1; t2=0; t3=0
playtune = 1
play music back.music_,1 'looping
timestart = 0

'-----------
' MAIN LOOP
'-----------
while not keydown(KEY_ESCAPE, true)
    'Music and Sound control
    if keydown(KEY_S,true) then
        stop music back.music_
        free music back.music_
        playtune=0
    endif

    'delta time
    t = clock(); dt = (t - lastTick)/1000; lastTick = t

    'player position in z
    player.z = player.z + player.speed*dt

    ' calculate camera y
    if int(player.z) < sizeof(road) - 2
        k = player.z%1
        player.y = (1 - k)*road[int(player.z)].y + k*road[int(player.z) + 1].y - 0.5
    else
        player.y = road[sizeof(road) - 1].y - 0.5
    endif

    'player's control
    if keydown(KEY_LEFT)  then
        player.x = player.x - player.speed*dt
        player.wheel = 90+10
        timestart = clock()
    endif
    if keydown(KEY_RIGHT) then
        player.x = player.x + player.speed*dt
        player.wheel = 90+5
        timestart = clock()
    endif
    timeduration = (clock() - timestart)/1000
    if timeduration > 0.5 then player.wheel = 0
        if keydown(KEY_UP,true)   and player.speed<12   then 
        player.speed = player.speed + 1
        if playtune=1 then; play sound player.gas,1; endif
    endif
    if keydown(KEY_DOWN,true) and player.speed>=1   then 
        player.speed = player.speed - 1
        if playtune=1 then; play sound player.gas,1; endif
    endif
    if player.speed > 1 then
       player.speed = player.speed - 0.001
    endif
    if keydown(KEY_SPACE,true) player.speed = 0

    'draw background image
    set color white; draw image back[theme], 0, -80 - player.y*player.speed

    '---------------------- draw road, tunnel, tree ---------------------   
    S3D_Clear()
    S3D_Translate(-player.x, -player.y, -player.z)
    S3D_Begin(S3D_QUADS)
    didFill = false

    strips = 0
    fills = 0

    for i = int(player.z) + 20 to int(player.z)
        if i < sizeof(road) - 2
            strips = strips + 1
            ' Do we need to fill with snow color to hide distant objects?
            S3D_Project(projected, 0, road[i + 1].y, i + 1)
            y0 = round(projected[1])
            S3D_Project(projected, 0, road[i].y, i)
            y1 = round(projected[1])
            if y1 > y0
                if not didFill
                    didFill = true
                    fills = fills + 1
                    set color land[theme]
                    draw rect 0, y0, width(primary), height(primary) - y0, true
                    set color white
                endif
            else
                didFill = false
            endif

            ' Draw road.
            x0 = road[i].x
            x1 = road[i + 1].x
            set color white
            S3D_Texture(road[theme].img)
            S3D_Vertex(x0 - 2, road[i].y, i, 0, road.height_)
            S3D_Vertex(x0 + 2, road[i].y, i, road.width_, road.height_)
            S3D_Vertex(x1 + 2, road[i + 1].y, i + 1, road.width_, 0)
            S3D_Vertex(x1 - 2, road[i + 1].y, i + 1, 0, 0)
           
            ' Draw sprites.
            ' Fade in.
            z = (i + 1) - player.z
            if z > 15
                a = ((20 - z)/5)*255
                set color white_alpha
            endif
            if i%20 = 0
                S3D_Texture(tunnel[theme])
                S3D_Vertex(road[i].x - 5, road[i].y + 0.2, i, 0, height(tunnel[1]))
                S3D_Vertex(road[i].x + 5, road[i].y + 0.2, i, width(tunnel[1]), height(tunnel[1]))
                S3D_Vertex(road[i].x + 5, road[i].y - 3.5, i, width(tunnel[1]), 0)
                S3D_Vertex(road[i].x - 5, road[i].y - 3.5, i, 0, 0)               
            else
                if i%2 = 0
                    S3D_Texture(tree[theme])
                    x = x0 - 2.5               
                    S3D_Vertex(x - 0.4, road[i].y, i, 0, height(tree[theme]))
                    S3D_Vertex(x + 0.4, road[i].y, i, width(tree[theme]), height(tree[theme]))
                    S3D_Vertex(x + 0.4, road[i].y - 1, i, width(tree[theme]), 0)
                    S3D_Vertex(x - 0.4, road[i].y - 1, i, 0, 0)
                else
                    S3D_Texture(tree[theme])
                    x = x0 + 2.5               
                    S3D_Vertex(x - 0.4, road[i].y, i, 0, height(tree[theme]))
                    S3D_Vertex(x + 0.4, road[i].y, i, width(tree[theme]), height(tree[theme]))
                    S3D_Vertex(x + 0.4, road[i].y - 1, i, width(tree[theme]), 0)
                    S3D_Vertex(x - 0.4, road[i].y - 1, i, 0, 0)
                endif
            endif
        endif
    next
    S3D_End()
    '---------------------------------------------------------------------------------
   
    'theme
    set color red
    set caret 250,190; wln "Theme"
    draw rect 250,210,20,20,t1
    draw rect 270,210,20,20,t2
    draw rect 290,210,20,20,t3
    if keydown(KEY_1,true) then 'winter
        theme = 1; if playtune=1 then PlayTune(1)
        t1=1;t2=0;t3=0
    endif
    if keydown(KEY_2,true) then 'tropical
        theme = 2; if playtune=1 then PlayTune(1)
        t1=0;t2=1;t3=0
    endif
    if keydown(KEY_3,true) then 'night
        theme = 3; if playtune=1 then PlayTune(1)
        t1=0;t2=0;t3=1
    endif
   
    'Speedometer
    set color red; set caret 46,170; wln round(player.speed)
    angle = player.speed*30
    y = height(primary)-50
    set color red
    draw ellipse 50,y,40,40 ; draw ellipse 50,y,41,41
    draw ellipse 50,y,5,5,1 
    draw line 49,y-1, 49+30*cos(rad(80+angle)),y-1+30*sin(rad(80+angle))
    draw line 50,y  , 50+30*cos(rad(80+angle)),y+30*sin(rad(80+angle))
    draw line 51,y+1, 51+30*cos(rad(80+angle)),y+1+30*sin(rad(80+angle))
   
    'Draw Player
    set color white; Draw(player.img,170,220,player.wheel)

    redraw
    wait 1
wend

'-----------
' FUNCTIONS
'-----------
function Draw(img,x,y,a)
    ' DrawImageTransformed(image, x, y, scale_x, scaleY, angle, pivot_x, pivot_y)
    ' Parameter :
    '   image               = .png format
    '   (x,y)               = location of the image in the screen coordinates
    '   scale_x, scale_y    = scale the image's size
    '   angle               = in radian.
    '   (pivot_x, pivot_y)  = center point of the image. E.g:(0,0) = top left.
    x = x; y = y ; s = 1; a=a; px = width(img)/2; py = height(img)/2
    DrawImageTransformed(img, x,y, s, s, a, px, py)
endfunc



RE: Rotated and scaled image drawing - Marcus - 03-15-2024

(03-15-2024, 11:35 AM)1micha.elok Wrote:
(03-14-2024, 07:00 PM)Marcus Wrote: ... The s3d library used here ....
You might need to install n7 version 24.03.10 ...

TEST DRIVE
Three different themes on the racing game : winter, tropical, night

click the image to zoom in

Control :
 - movement            : LEFT, RIGHT
 - speed                   : UP, DOWN
 - stop                     : SPACE
 - theme selection     : 1 = winter, 2 = tropical, 3 = night
 - quit                      : ESC
 - music,sound off     : S

 Acknowledgements :
 This game would not be possible without
 1. Marcus for New Libraries
    -s3d.n7 library, required version N7_240310
    -racing.n7, example how to use s3d library
    -SquareWave(), sfx.n7 library
    -DrawImageTransformed()
 2. Johnno for every valuable suggestion
 3. Sprites
    - https://pngtree.com/so/steering-wheel
    - https://opengameart.org/content/25d-racing-resources
 4. Music and Acceleration Sound https://pixabay.com

Code:
'========================================
' TEST DRIVE
'
' Control :
' - movement        : LEFT, RIGHT
' - speed           : UP, DOWN
' - stop            : SPACE
' - theme selection : 1 = winter
'                     2 = tropical
'                     3 = night
' - quit            : ESC
' - music,sound off : S
'
' Note :
' This game is just a proof of concept.
' There are still some tasks left opened.
' (collision, road track, finish line, etc.)
'
' Acknowledgements :
' This game would not be possible without
' 1. Marcus for New Libraries
'    -s3d.n7 library, required version N7_240310
'    -racing.n7, example how to use s3d library
'    -SquareWave(), sfx.n7 library
'    -DrawImageTransformed()
' 2. Johnno for every valuable suggestion
' 3. Sprites
'    - https://pngtree.com/so/steering-wheel
'    - https://opengameart.org/content/25d-racing-resources
' 4. Music and Acceleration Sound https://pixabay.com
'==============================================

'-----------------
' INITIALIZATION
'-----------------
' Marcus : A library that I'm working on, not finished at all, don't use it!
' Micha  : Oops...sorry, I use it :)
include "assets/s3d.n7"
S3D_SetView(primary, rad(90), 0.1, 20)' Set up 3d view.
S3D_SetDirectMode(true) 'true = draw from back to front manually
include "assets/soundtune.n7"
include "assets/transform.n7"

#win32
'#dbg
set window "TEST DRIVE", 320, 240, false, 2
set redraw off

'color definition
white         = [255,255,255]
white_alpha   = [255,255,255,255]
gray          = [218,218,218]
green         = [0,200,0]
black         = [50,50,50]
red           = [255,0,0]

'road
road = []
for z = 0 to 999  road[z] = [x: sin(z*0.05)*6, y: sin(z*0.1)*3]
road[1].img     = loadimage("assets/road_winter.png")
road[2].img     = loadimage("assets/road_beach.png")
road[3].img     = loadimage("assets/road_city.png")
road.width_     = width(road[1].img)
road.height_    = height(road[1].img)

'decorations
land        = []
land[1]     = gray
land[2]     = green
land[3]     = black
tree        = []
tree[1]     = loadimage("assets/tree_winter.png")
tree[2]     = loadimage("assets/tree_palm.png")
tree[3]     = loadimage("assets/house.png")
tunnel      = []
tunnel[1]   = loadimage("assets/tunnel_winter.png")
tunnel[2]   = loadimage("assets/tunnel_green.png")
tunnel[3]   = loadimage("assets/tunnel_city.png")
back        = []
back[1]     = loadimage("assets/sky_winter2.png")
back[2]     = loadimage("assets/sky_tropical.png")
back[3]     = loadimage("assets/sky_night.png")
back.music_ = loadmusic("assets/rock.wav")

'player
player = []
player.z = 0.0
player.x = 0
player.y = -1
player.speed = 0
player.gas = loadsound("assets/acceleration.wav")
player.img = loadimage("assets/wheel.png")
player.wheel = 0

'misc initial values
projected = dim(4) ' Don't want to spawn too many tables in a game loop, reused for calculations.
lastTick = clock()
theme  = 1 ;t1 = 1; t2=0; t3=0
playtune = 1
play music back.music_,1 'looping
timestart = 0

'-----------
' MAIN LOOP
'-----------
while not keydown(KEY_ESCAPE, true)
    'Music and Sound control
    if keydown(KEY_S,true) then
        stop music back.music_
        free music back.music_
        playtune=0
    endif

    'delta time
    t = clock(); dt = (t - lastTick)/1000; lastTick = t

    'player position in z
    player.z = player.z + player.speed*dt

    ' calculate camera y
    if int(player.z) < sizeof(road) - 2
        k = player.z%1
        player.y = (1 - k)*road[int(player.z)].y + k*road[int(player.z) + 1].y - 0.5
    else
        player.y = road[sizeof(road) - 1].y - 0.5
    endif

    'player's control
    if keydown(KEY_LEFT)  then
        player.x = player.x - player.speed*dt
        player.wheel = 90+10
        timestart = clock()
    endif
    if keydown(KEY_RIGHT) then
        player.x = player.x + player.speed*dt
        player.wheel = 90+5
        timestart = clock()
    endif
    timeduration = (clock() - timestart)/1000
    if timeduration > 0.5 then player.wheel = 0
        if keydown(KEY_UP,true)   and player.speed<12   then 
        player.speed = player.speed + 1
        if playtune=1 then; play sound player.gas,1; endif
    endif
    if keydown(KEY_DOWN,true) and player.speed>=1   then 
        player.speed = player.speed - 1
        if playtune=1 then; play sound player.gas,1; endif
    endif
    if player.speed > 1 then
       player.speed = player.speed - 0.001
    endif
    if keydown(KEY_SPACE,true) player.speed = 0

    'draw background image
    set color white; draw image back[theme], 0, -80 - player.y*player.speed

    '---------------------- draw road, tunnel, tree ---------------------  
    S3D_Clear()
    S3D_Translate(-player.x, -player.y, -player.z)
    S3D_Begin(S3D_QUADS)
    didFill = false

    strips = 0
    fills = 0

    for i = int(player.z) + 20 to int(player.z)
        if i < sizeof(road) - 2
            strips = strips + 1
            ' Do we need to fill with snow color to hide distant objects?
            S3D_Project(projected, 0, road[i + 1].y, i + 1)
            y0 = round(projected[1])
            S3D_Project(projected, 0, road[i].y, i)
            y1 = round(projected[1])
            if y1 > y0
                if not didFill
                    didFill = true
                    fills = fills + 1
                    set color land[theme]
                    draw rect 0, y0, width(primary), height(primary) - y0, true
                    set color white
                endif
            else
                didFill = false
            endif

            ' Draw road.
            x0 = road[i].x
            x1 = road[i + 1].x
            set color white
            S3D_Texture(road[theme].img)
            S3D_Vertex(x0 - 2, road[i].y, i, 0, road.height_)
            S3D_Vertex(x0 + 2, road[i].y, i, road.width_, road.height_)
            S3D_Vertex(x1 + 2, road[i + 1].y, i + 1, road.width_, 0)
            S3D_Vertex(x1 - 2, road[i + 1].y, i + 1, 0, 0)
           
            ' Draw sprites.
            ' Fade in.
            z = (i + 1) - player.z
            if z > 15
                a = ((20 - z)/5)*255
                set color white_alpha
            endif
            if i%20 = 0
                S3D_Texture(tunnel[theme])
                S3D_Vertex(road[i].x - 5, road[i].y + 0.2, i, 0, height(tunnel[1]))
                S3D_Vertex(road[i].x + 5, road[i].y + 0.2, i, width(tunnel[1]), height(tunnel[1]))
                S3D_Vertex(road[i].x + 5, road[i].y - 3.5, i, width(tunnel[1]), 0)
                S3D_Vertex(road[i].x - 5, road[i].y - 3.5, i, 0, 0)               
            else
                if i%2 = 0
                    S3D_Texture(tree[theme])
                    x = x0 - 2.5               
                    S3D_Vertex(x - 0.4, road[i].y, i, 0, height(tree[theme]))
                    S3D_Vertex(x + 0.4, road[i].y, i, width(tree[theme]), height(tree[theme]))
                    S3D_Vertex(x + 0.4, road[i].y - 1, i, width(tree[theme]), 0)
                    S3D_Vertex(x - 0.4, road[i].y - 1, i, 0, 0)
                else
                    S3D_Texture(tree[theme])
                    x = x0 + 2.5               
                    S3D_Vertex(x - 0.4, road[i].y, i, 0, height(tree[theme]))
                    S3D_Vertex(x + 0.4, road[i].y, i, width(tree[theme]), height(tree[theme]))
                    S3D_Vertex(x + 0.4, road[i].y - 1, i, width(tree[theme]), 0)
                    S3D_Vertex(x - 0.4, road[i].y - 1, i, 0, 0)
                endif
            endif
        endif
    next
    S3D_End()
    '---------------------------------------------------------------------------------
   
    'theme
    set color red
    set caret 250,190; wln "Theme"
    draw rect 250,210,20,20,t1
    draw rect 270,210,20,20,t2
    draw rect 290,210,20,20,t3
    if keydown(KEY_1,true) then 'winter
        theme = 1; if playtune=1 then PlayTune(1)
        t1=1;t2=0;t3=0
    endif
    if keydown(KEY_2,true) then 'tropical
        theme = 2; if playtune=1 then PlayTune(1)
        t1=0;t2=1;t3=0
    endif
    if keydown(KEY_3,true) then 'night
        theme = 3; if playtune=1 then PlayTune(1)
        t1=0;t2=0;t3=1
    endif
   
    'Speedometer
    set color red; set caret 46,170; wln round(player.speed)
    angle = player.speed*30
    y = height(primary)-50
    set color red
    draw ellipse 50,y,40,40 ; draw ellipse 50,y,41,41
    draw ellipse 50,y,5,5,1 
    draw line 49,y-1, 49+30*cos(rad(80+angle)),y-1+30*sin(rad(80+angle))
    draw line 50,y  , 50+30*cos(rad(80+angle)),y+30*sin(rad(80+angle))
    draw line 51,y+1, 51+30*cos(rad(80+angle)),y+1+30*sin(rad(80+angle))
   
    'Draw Player
    set color white; Draw(player.img,170,220,player.wheel)

    redraw
    wait 1
wend

'-----------
' FUNCTIONS
'-----------
function Draw(img,x,y,a)
    ' DrawImageTransformed(image, x, y, scale_x, scaleY, angle, pivot_x, pivot_y)
    ' Parameter :
    '   image               = .png format
    '   (x,y)               = location of the image in the screen coordinates
    '   scale_x, scale_y    = scale the image's size
    '   angle               = in radian.
    '   (pivot_x, pivot_y)  = center point of the image. E.g:(0,0) = top left.
    x = x; y = y ; s = 1; a=a; px = width(img)/2; py = height(img)/2
    DrawImageTransformed(img, x,y, s, s, a, px, py)
endfunc

This is really cool Big Grin

Edit Note that the s3d library will go through many changes before I release it for real. But your program will of course continue to function with the test version of the library that you've used now.


RE: Rotated and scaled image drawing - johnno56 - 03-15-2024

Definitely VERY cool... I particularly like the "night" theme.... Very nicely done!


RE: Rotated and scaled image drawing - kevin - 03-16-2024

Really impressive, especially considering that you did everything in 9 days (I normally manage about 10% of any project in that sort of time Smile).
I did get an error message pop up after a couple of minutes - it seems to relate to the S3D drawing routine, so may be useful to you and Marcus:

   

All the best ... Kevin


RE: Rotated and scaled image drawing - 1micha.elok - 03-16-2024

(03-16-2024, 01:19 PM)kevin Wrote: Really impressive, especially considering that you did everything in 9 days (I normally manage about 10% of any project in that sort of time Smile).
I did get an error message pop up after a couple of minutes - it seems to relate to the S3D drawing routine, so may be useful to you and Marcus:



All the best ... Kevin

All the credit, the trophy, and the award for this achievement should go to Marcus, thanks to him that he did every kind of impossible things such as curved road, texture mapping and all the awesome new libraries .... He inspires me that there are endless possibilities, beyond human imagination in game programming.
My part was just a small part of the game, just code a piece of steering wheel and speed ... and the brake to stop the car  Big Grin


RE: Rotated and scaled image drawing - johnno56 - 03-17-2024

True... Marcus is the source of the Rotation and Scaling routine... But, who was it that used that routine to create the first version of the game? "My part was just a small part of the game"... Without the initial "small part" there probably would not be a game. We are a forum. We are here to help. Ultimately this is 'your' game... I personally am impressed that you have done SO much in such a short time! Imagine what you could do if you had assigned yourself even more time?

Well done!