News:

Function Finder  Find all the functions within source code files

Main Menu

Simulate a zoom like GTA 1

Started by ale870, September 27, 2006, 01:52:13 AM

Previous topic - Next topic

ale870

Did you see/remember GTA 2D?

Well, I wanted to realize a zoom effect like that: when my car (race game I'm creating) accelerates, the camera will zoom-out; when the car brakes, then the camera will make a zoom-in.

I wanted to realize this effect using a "mapper" between the world and CAMERA. Example (I already made it in Game Maker using a similar technique):

Camera has a specific dimension (e.g.: 800x600).

Camera has 4 parameters that indicate which area it is watching. It means: if the area it is watching have the same size of camera size, then we have no zoom, else camera will zoom it.

Ok, a little bit confusing. I try again to explain.

Example:

* My world is 3000x3000
* Screen size is 800x600
* Camera size is 800x600 (camera cover all the screen)
* If camera is watching an area of 1600x1200: zooming out 2x
* If camera is watching an area of 400x300: zooming in 2x

It could be an alternative solution if we could apply a specific zoom:

setCameraZoom 2    // Camera zoom-in 2x
setCameraZoom -2    // Camera zoom-out 2x

What can I do in PB?  ???







--Alessandro

ale870

#1
Hello, I tried to simulate it using TextureQuad, but framerate goes down very quickly  :(

PlayBASIC Code: [Select]
; PROJECT : Project1
; AUTHOR :
; CREATED : 25/9/2006
; EDITED : 27/9/2006
; ---------------------------------------------------------------------

Explicit

// Create world

Local world = GetFreeImage()
CreateImage world, 2000, 2000

// Create camera

Local camera1 = GetFreeCamera()
CreateCamera camera1

// Load image TILE

Local tile1 = GetFreeImage()
LoadImage "ground01.jpg", tile1

// Create scene buffer

Local sceneBuffer = GetFreeImage()
CreateImage sceneBuffer, GetScreenWidth(), GetScreenHeight()

// Sprite

Local imgSportinaTile = GetFreeImage()
LoadImage "SPORTROSSA128.png", imgSportinaTile

// Get single image to be used for sprite

Local imgSportina = GetFreeImage()

RenderToImage imgSportinaTile
GetImage imgSportina, 0, 0, 127, 127
RenderToScreen

PrepareFXImage imgSportina
ImageMaskColour imgSportina, RGB(255, 0, 255)

// Set sprite details

Local sprSportina = GetFreeSprite()
CreateSprite sprSportina
SpriteImage sprSportina, imgSportina

Ink $ffffff

PositionSprite sprSportina, 300, 200
SpriteTransparent sprSportina, 1
SpriteDrawMode sprSportina, 2

CenterSpriteHandle sprSportina

// Drawing World

RenderToImage world
GridImage tile1, 0, 0, 10, 10, 1

;getImage world, 0, 0, GetScreenWidth(), GetScreenHeight()
CopyRect world, 0, 0, GetScreenWidth(), GetScreenHeight(), sceneBuffer, 0, 0

Local i = 0
Local zx#, zy#

Do
;CopyRect world, i, i, GetScreenWidth()+i-1, GetScreenHeight()+i-1, sceneBuffer, 0, 0
RenderToImage sceneBuffer
;TextureQuad tile1, 0, 0, 0, 0, 800, 0, 800, 0, 0, 600, 0, 600, 800, 600, 800, 600, 0
drawScaledImage(tile1, 0, 0, 1+zx#, 1+zy#)

If LeftKey() Then i = i - 1
If RightKey() Then i = i + 1
zx# = zx# + 0.01
zy# = zy# + 0.01
RotateSprite sprSportina, i
DrawSprite sprSportina

Text 0, 0, FPS()

RenderToScreen
DrawImage sceneBuffer, 0, 0, 0

Sync
Loop

Function DrawScaledImage(ImageIndex,xpos,ypos,ScaleX#,ScaleY#)
Static W, H, nw, nh, x1, x2, x3, x4, y1, y2, y3, y4, u1, u2, u3, u4, v1, v2, v3, v4

If GetImageStatus(imageindex)
W=GetImageWidth(imageindex)
H=GetImageHeight(imageindex)

nw=w*scalex#
nh=h*scaley#
x1=xpos
y1=ypos
u1=0 * $10000
v1=0 * $10000
x2=xpos+nw
y2=ypos
u2=(w-1)*$10000
v2=0 * $10000
x3=xpos+nw
y3=ypos+nh
u3=(w-1)*$10000
v3=(h-1)*$10000
x4=xpos
y4=ypos+nh
u4=0 * $10000
v4=(h-1)* $10000

TextureQuad imageindex,x1,y1,u1,v1,x2,y2,u2,v2,x3,y3,u3,v3,x4,y4,u4,v4,0
EndIf
EndFunction



I took the function "DrawScaledImage" from your examples  ::)

My framerate start from 400 fps (without rescaling) up to 50fps after rescaling was applied. You can see I didn't use real World object, and did not use camera, but I simulated them using an image as buffer. This system works perfectly, and is very flexible  ;)

The real problem is camera zooming functionality should be implemented at low level (PB code).

Have you any other ideas?

Thank you!





--Alessandro

kevin


  Does the viewer need to rotate the scene ?


kevin

 Change this


// Load image TILE
Local tile1 = GetFreeImage()
LoadImage "ground01.jpg", tile1




// Load image TILE
Local tile1 = GetFreeImage()
LoadFXImage "ground01.jpg", tile1



ale870

I don't need rotation.
WOWWW!!!!!    ;D ;D ;D

Simply incredible!!

Now it works! It's great!

This was the trick I was looking for!

In my game, I will put official thank (in about box) to you!

Simply great!

Thank you again Kevin!   :)
--Alessandro

stef


The possibilty for zooming/fast-scaling is indeed extremly important.

In the example above it would be necessary to recalculate every item in a world system (positition of sprites,speed size,etc.)

Will there be better possibilites (to use in world/camera-system) with PBFX?



stef

#6
this is a example

it's realtime scaling a image 800*600  to 400*300
in world/camerasystem

the camera is moving along the grey circle,camera-imagesize(viewport)=800*600
the image is simply scaled in realtime with scaleimage command to 400*300

too slow for use that way


PlayBASIC Code: [Select]
OpenScreen 800,600,16,2

Gosub drawstuff

Do

xf=800
yf=600

World1=GetFreeWorld()
CreateWorld World1
CaptureToWorld world1


h1=GetFreeImage()
CreateImage h1,xf,yf
RenderToImage h1

Camera1=GetFreeCamera()
CreateCamera Camera1
CameraViewPort camera1,0,0,xf,yf
Global Camera1

PositionCamera camera1,(CosNewValue(1500,rotangle#,1350))-xf/2, (SinNewValue(1500,rotangle#,1350))-yf/2

rotangle#=rotangle#+1

DrawImage background,0,0,1

CaptureToScene

ClsScene

CameraGrabWorld Camera1,world1

DrawCamera Camera1

RenderToScreen
Cls 0



ScaleImage h1,xf/2,yf/2,1
DrawImage h1,0,0,1

Text 0,0,Str$(FPS())


Sync
DeleteCamera camera1
DeleteWorld World1
DeleteImage h1
DeleteSprite h1sp

Loop
WaitKey

drawstuff:
background=NewImage(3000,3000)

tile =NewImage(100,100)
RenderToImage tile
Cls 60
BoxC 0,0,50,50,1,RGB(0,0,80)
BoxC 51,51,100,100,1,RGB(0,0,80)

lap=NewImage(3000,3000)
RenderToImage lap

CircleC 1500,1500,1400,1,RGB(100,100,100)
CircleC 1500,1500,1300,1,RGB(0,0,0)

RenderToImage background
TileImage tile,0,0,1
DrawImage lap,0,0,1
Return








ale870

#7
I created a version of GTA like zoom.
Even if it contains "dirty" code (not optimized, this is the first working version I created!), it works!

In my computer I work from 250 fps up-to 290 fps.
I introduced a lazy-trick: I work in standard resolution (e.g.: 800x600) for zoom-out (or no-zoom applied). Since I need more power when the car is running (user needs a strong feedback, and I need real power!) I draw the screen using DrawImage; when the car stops, the program will zoom (in) to the vehicle, and I enable TextureQuad drawing system.

Sorry for some italian text!

I hope this will help you!

I will put a tutorial on my site as soon as possible ("how to create GTA-like zoom effect").

PlayBASIC Code: [Select]
; PROJECT : Project1
; AUTHOR :
; CREATED : 25/9/2006
; EDITED : 29/9/2006
; ---------------------------------------------------------------------

Explicit

;GfxMMX True

Cls 0
Ink $ffffff
Print "Usa le frecce per muovere il veicolo."
Print "Usa SPAZIO per fermarlo istantaneamente."
Print "Usa ENTER per passare da un 60 FPS fissi a FPS illimitati"
Print " (usalo per testare gli FPS massimi)"
Print ""
Print ""
Print "Premi un tasto..."

Sync
WaitKey

SetFPS(60)

// Load FONT

LoadFont "Courier New", 1, 14, 1
MakeBitmapFont 1, $ffffff
SetFont 1

// Create world

Local world = GetFreeImage()
CreateFXImage world, 5000, 5000

// Load image TILE

Local tile1 = GetFreeImage()
LoadFxImage "ground01.jpg", tile1

// Create scene buffer

Local sceneBuffer = GetFreeImage()
CreateFXImage sceneBuffer, GetScreenWidth(), GetScreenHeight()

//
// Sprite
//

Local imgSportina = GetFreeImage()
LoadFxImage "SPORTROSSA128.png", imgSportina

/* Get single image To be used For sprite. */

// SPORTINA 128x128

PrepareFXImage imgSportina
ImageMaskColour imgSportina, RGB(255, 0, 255)

// Set sprite details

Local sprSportina = GetFreeSprite()
CreateSprite sprSportina
SpriteImage sprSportina, imgSportina


CenterSpriteHandle(sprSPortina)

SpriteTransparent sprSportina, 1
SpriteDrawMode sprSportina, 2
PositionSprite sprSportina, GetScreenWidth() / 2, GetScreenHeight() / 2

// Drawing World

Ink $ffffff

RenderToImage world
GridImage tile1, 0, 0, 50, 50, 1

;
;CopyRect world, 0, 0, GetScreenWidth(), GetScreenHeight(), sceneBuffer, 0, 0

Local i = 0
Local a# = 0
Local velocita# = 0
Local worldX# = GetImageWidth(world) / 2 - GetScreenWidth() / 2
Local worldY# = GetImageHeight(world) / 2 - GetScreenHeight() / 2

/* Vale:
"in" = effettuo uno zoom in;
"out" = effettuo uno zoom out.
*/


Local zoomInOutNone$ = "out"

Constant SPEED_ZOOM_IN# = -0.01
Constant SPEED_ZOOM_OUT# = 0.01
Constant MAX_ZOOM_FACTOR# = 0.5

// Vale <>0 quando sono in fase di zoom in/out */

Local zooming# = 0
Local zoomFactor# = 0

Do
;CopyRect world, worldX#, worldY#, GetScreenWidth()+worldX#-1, GetScreenHeight()+worldY#-1, sceneBuffer, (GetScreenWidth() * zoomFactor# / 2), (GetScreenHeight() * zoomFactor# / 2)
CopyRect world, worldX#, worldY#, GetScreenWidth()+worldX#-1, GetScreenHeight()+worldY#-1, sceneBuffer, 0, 0

// Gestione direzione veicolo

If LeftKey() Then i = i - 2
If RightKey() Then i = i + 2

// Freno a mano
If SpaceKey() Then velocita# = 0

// Gestione velocita`

If UpKey() Then velocita# = velocita# + 0.1
If DownKey() Then velocita# = velocita# - 0.1

If EnterKey()
If GetFPS() <> 0
SetFPS(0)
Wait 500
Else
SetFPS(60)
Wait 500
EndIf
EndIf

If Abs(velocita#) = 0 And zoomInOutNone$ = "out" And zooming# = 0
zooming# = SPEED_ZOOM_IN#
ElseIf velocita# <> 0 And zoomInOutNone$ = "in" And zooming# = 0
zooming# = SPEED_ZOOM_OUT#
EndIf

If zooming# < 0
If zoomFactor# < -MAX_ZOOM_FACTOR#
zooming# = 0
zoomInOutNone$ = "in"
zoomFactor# = -MAX_ZOOM_FACTOR#
Else
zoomFactor# = zoomFactor# + zooming#
ScaleSprite sprSportina, 1 - zoomFactor#
EndIf

ElseIf zooming# > 0
Login required to view complete source code


--Alessandro