Help me, about 2D x,y

Blitz3D Forums/Blitz3D Beginners Area/Help me, about 2D x,y

Apollonius(Posted 2004) [#1]
Well, if you make somekind of game and ask to draw and image to 5000,5000

Does it start from the top left corner? And how can u move ur screen to move down,up,left,right and get to that image? or does the image move with the corner of ur screen... i dunno if u can follow me :|

and example would be nice, like how to make ur screen move...


sswift(Posted 2004) [#2]
Your screen is 0,0 in the top left corner, and GraphicsWidth()-1, GraphicsHeight()-1 in the lower right corner.

If you want to scroll an image onto the screen, then you need to move the images, not the screen.

Luckilly, this is fairly easy to do.

Let's assume Screen_X, Screen_Y is where you would like the screen to be in the 2D plane that extends both to -5000,-5000 and to 5000, 5000.

As the screen itself cannot move, you need to instead offset the images to simulate the effect.

All you need to do then is subtract Screen_X and Screen_Y from the image's location in the world, and then blit the image to that new location.

Ie, if your image is at 5000,5000, and your screen is at 4000, 4000, then you would blit the image at 1000,1000.

Note though that this is very likely to be off the screen, because most 2D games do not run at 1280x1024. They run at more like 640x480, or 800x600. Can't scroll graphics at a high framerate in really high resolutions.


Neo Genesis10(Posted 2004) [#3]
You should avoid actually drawing an image of that size to the screen though. Use DrawImageRect to draw only the area of the image which is onscreen.


Apollonius(Posted 2004) [#4]
What I meant was,

example I place a circle at x5000,y5000 and the screen appears at x0,y0 if I press up the screen moves up, down the screen moves down(like scrolling,left the screen moves left and right the screen moves right, but the circle doesn't move the screen does :P

Another question, if I added a space background and like my spaceship goes right, so the background scrolls left at a certain speed, how would I do that? is that doable?


sswift(Posted 2004) [#5]
You MUST move the images. You CANNOT move "the screen". The screen is not a camera providing a view into a larger world, it is a collection of pixels a certan width and height fixed in place.

Moving the images in the way I describe will make the screen APPEAR to move. It will be the effect you want.

The screen only APPEARS to be a window into a larger area when you offset the images before you draw them.

So in my example above, add 10 to Screne_X every tiem the user hits right arrow, and that will make the images move to the left... which will make the screen viewport appear to move to the right.

Blitting big images though is not the best way to make a scrolling engine. The best way is to scroll is to use small tiles.


You may be thinking of how one used to scroll graphics in the sayd of DOS. Back then you could make the graphics buffer bigger than the screen, and scroll parts of it into view, then when one whole tile was revealed you could build some more off the edge waiting to scroll onto the screen, and continue to scroll.

But as far as I know, this method of scrolling is no longer possible.

That method isn't that useful anyhow, because noawadays most 2D games have parralax. And the fastest way to do parralax is just to redraw the whole screen every time.


"Another question, if I added a space background and like my spaceship goes right,"

Yes, you can do this. All you need to do is change the spaceship position in the world. So as you are changing screen_X, and subtracting that from the space ship and background tile positions just before you draw them, you also are adding some value to ship_X so that it is moving to the right faster than the screen is scrolling to the left.

Of course, in MOST shooters, they are not realistic, so if you move the ship to the right, it stays there even though the screen scrolls. In that case, you simply position the ship in screen space, and don't subtract screen_X, Screen_Y from it's location every frame. Then it'll stay at Ship_X, Ship_Y on the screen where you left it.


sswift(Posted 2004) [#6]
Again to reiterate:

Image_X, Image_Y = Image location in WORLD space.
Screen_X, Screen_Y = Screen location in WORLD space.
Ship_X, ShipY = Ship location in SCREEN space.


During each loop:

To scroll background left: Screen_X = Screen_X - 10
Draw background Image at: Image_X-Screen_X, ImageY-Screen_Y.
Draw Ship at: Ship_X, Ship_Y


If you want the ship to move back when the screen scrolls left, then instead draw it at Ship_X-Screen_X, Ship_Y-Screen_Y. But remember that you will have to move it to the right at the same speed as the screen is scrolling left if you want to keep it on the screen.


Apollonius(Posted 2004) [#7]
I tryed something which is not working, what am i doing wrong:

; Graphic Mode
Graphics 800,600,32

; Global Variables


While Not KeyDown(1)

Cls ; Always clear screen first

Rect 40,40,20,20,1 ; Draw the box in the current x,y location
Rect 40,100,20,20,1 ; Draw the box in the current x,y location

If KeyHit(208) Then
ch=GraphicsHeight() - 1
EndIf

Flip ; Flip it into view

Wend


sswift(Posted 2004) [#8]
You're doing a lot wrong. I'm not even sure what you intended with that bit that gets activated when you press a key.

Here is the simplest 2d scrolling system I could muster up for you.

Graphics 800,600,32
SetBuffer BackBuffer()

Type Sprite 
	Field Image 
	Field XPos
	Field YPos
End Type

Dim Image(20)


; Create 20 random images to use for sprites cause we don't have any bitmaps to load.
For Loop = 0 To 19

	Image(Loop) = CreateImage(32, 32)
	
	SetBuffer ImageBuffer(Image(Loop))
	Color Rand(0,255), Rand(0,255), Rand(0,255)
	
	Shape = Rand(0, 1)

	Select Shape

		Case 0 
			Rect 0, 0, 32, 32, Rand(0, 1)

		Case 1
			Oval 0, 0, 32, 32, Rand(0, 1)

	End Select

Next


; Reset the graphics to draw to the backbuffer.  
; Don't need to do this if you load the images instead of create them manually.
SetBuffer BackBuffer()


; Create 2000 random sprites in the world.  
For Loop = 1 To 2000
	
	; Add a new sprite to the list of sprites.
	ThisSprite.Sprite = New Sprite
	
	; Pick a random image for this sprite.
	ThisSprite\Image = Image(Rand(0, 19))

	; Place the sprite at a random location in world space.
	ThisSprite\XPos = Rand(0, 10000)
	ThisSprite\YPos = Rand(0, 10000)
	
Next


; Set the initial position of the "camera".
Screen_X = 5000
Screen_Y = 5000


While Not KeyDown(1)

	Cls 

	; Use arrow keys to "scroll".	
	If KeyDown(203) Then Screen_X = Screen_X - 1
	If KeyDown(205) Then Screen_X = Screen_X + 1
	If KeyDown(200) Then Screen_Y = Screen_Y - 1
	If KeyDown(208) Then Screen_Y = Screen_Y + 1

	; Draw all objects in the world.
	For ThisSprite.Sprite = Each Sprite
		DrawImage ThisSprite\Image, ThisSprite\XPos-Screen_X, ThisSprite\YPos-Screen_Y
	Next
	
	Flip 

Wend



soja(Posted 2004) [#9]
#1 - Everytime the user presses down, you're just saying "ch=599"... what's ch? It doesn't do anything.

#2 - It looks like you're trying to "move" the screen.

Try assigning variables to the x,y positions of the rectangles (before the While loop) instead of 40,40 and 40,100, then when the user presses an arrow, alter the x,y variables.


sswift(Posted 2004) [#10]
Btw, Drawimage draws any areas of an image that have color 0,0,0 as transparent. For your backgrounds you may want to use drawblock instead, unless you have multiple layers scrolling on top of one another.


Kevin_(Posted 2004) [#11]
Kaisuo....

Your signature says that you have Blitz Plus. If that is the case then you can indeed move the screen without having to draw your graphics all of the time.

All you do is create a canvas that is larger than the window area then use SetGadgetShape on your canvas to reposition the canvas. Ideal for scrolling shoot em ups etc.


sswift(Posted 2004) [#12]
"All you do is create a canvas that is larger than the window area then use SetGadgetShape on your canvas to reposition the canvas. Ideal for scrolling shoot em ups etc."

I'd be surprised if that was anything other than much slower than the method I described. :-)


Tiger(Posted 2004) [#13]
You can scroll without moveing Image objects, use the command Origin x,y; this sets a new point for all subsequent drawing commands.
Origin x,y can be negative or positive.

This is if you don't use canvas.


sswift(Posted 2004) [#14]
But then your HUD will draw out of place, and your ship will scroll with the screen. :-)


Tiger(Posted 2004) [#15]
sswift:
Yes they will follow the scroll, but you can set origin to 0,0 before drawing HUD and ship's, then they will stand still. :-\


Neo Genesis10(Posted 2004) [#16]
In a nutshell then, Kaisuo, what you need is OFFSET coordinates. An OFFSET is a value which will alter the co-ordinates of an object in order to draw it onscreen. So, taking your example, if you had an object at 5000, 5000 you would offset that by subtracting the offset values from the x and y co-ordinates. Here is a more practical example:
; Define our objects

Global OFFSET_X = 0		; Set to zero (it is by default anyway)
Global OFFSET_Y = 0

Global MAN_X = 5000		; Set the co-ordinates of our character
Global MAN_Y = 5000

Repeat
	If KeyDown(KEY_UP) MAN_Y = MAN_Y - SPEED
	If KeyDown(KEY_DOWN) MAN_Y = MAN_Y + SPEED
	If KeyDown(KEY_LEFT) MAN_X = MAN_X - SPEED
	If KeyDown(KEY_RIGHT) MAN_X = MAN_X + SPEED

	; Draw the area of the background which is onscreen
	DrawBlockRect mybackground, 0, 0, OFFSET_X, OFFSET_Y, GraphicsWidth(), GraphicsHeight()

	; If the character is onscreen then draw him

	TEST_X = MAN_X - OFFSET_X
	If TEST_X < GraphicsWidth() And TEST_X > -ImageWidth( MAN_IMAGE )
		TEST_Y = MAN_Y - OFFSET_Y
		If TEST_Y < GraphicsHeight() And TEST_Y > -ImageHeight(MAN_IMAGE)
			DrawImage MAN_IMAGE, TEST_X, TEST_Y
		EndIf
	EndIf

	Flip

Until KeyHit(1)
Notice that the values OFFSET_X are subtracted from the characters X and Y coordinates when checking to see if he is onscreen. In this example, the cursor keys would move the character but not scroll the map. To achieve this, you could set the keys to change the OFFSET_X and OFFSET_Y values instead.


Kevin_(Posted 2004) [#17]
SSwift....

I'd be surprised if that was anything other than much slower than the method I described. :-)


Prove it!


sswift(Posted 2004) [#18]
Easy enough for you to test yourself if you're that interested in the results. :-)


mudcat(Posted 2004) [#19]
Try this,the block you see is the main man,there is a block
down below the screen.Press down to walk to it.



;I tryed something which is Not working, what am i doing wrong:

; Graphic Mode
Graphics 800,600,32

; Global Variables

Global x=40,x1=40,y=40,y2=640
While Not KeyDown(1)

Cls ; Always clear screen first

Rect x,y,20,20,1 ; Draw the box in the current x,y location
Rect x1,y2,20,20,1 ; Draw the box in the current x,y location

If KeyHit(208) Then

y2=y2-40
EndIf

Flip ; Flip it into view

Wend


Is this what ur asking?