Tilemap, schon wieder

Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Neue Antwort erstellen

M0rgenstern

Betreff: Tilemap, schon wieder

BeitragMi, Apr 07, 2010 11:13
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey Leute.
Ich weiß, dass dieses Thema schon x-mal behandelt wurde. Ich hab mir im Prinzip schon jeden Beitrag den ich gefunden habe durchgelesen, aber trotzdem das passende nicht gefunden.
Ich habe mich entschieden AlienShooter 2D in BlitzMax umzuschreiben.
Ich habe dann direkt mit dem Mapeditor angefangen.

Mein Problem ist aber das SCrolling.
Ich hab schon versucht verschiedene Dinge nachzubasteln, aber das funktioniert alles nicht so ganz.
Problem ist folgendes: Ich habe im Prinzip die Spielerkoordinaten, die sich immer in der Bildschirmmitte befinden sollen. Die "Kamera" im Editor soll auch immer in der Bildschirmmitte sein.
Ich habs jetzt hinbekommen, dass die Map sich bewegt, aber das ganze sieht ehre seltsam als richtig aus.
Das Problem ist einfach, dass ich nicht genau weiß, wie ich das mit den Kamerakoordinaten verrechnen soll.

Ich hab hier mal den Code, der relevant ist:

Variablen:
BlitzMax: [AUSKLAPPEN]
Const iTilesize:Int = 32
Const iLayer:Int = 3
Global iMapwidth:Int = 60
Global iMapheight:Int = 60

Global fScrollX:Float = 0
Global fScrollY:Float = 0
Global fMoveX:Float = 0
Global fMoveY:Float = 0

Global fPlayerX:Float = GraphicsWidth() / 2 / iTilesize
Global fPlayerY:Float = GraphicsHeight() / 2 / iTilesize


Hauptschleife:

BlitzMax: [AUSKLAPPEN]
While Not KeyHit(KEY_ESCAPE) Or AppTerminate()
WaitTimer(FTimer)
Cls

If KeyDown(KEY_UP) Then
fMoveY = fMoveY - 1
fScrollY = fPlayerY - fMoveY
EndIf
If KeyDown(KEY_DOWN) Then
fMoveY = fMoveY + 1
fScrollY = fPlayerY - fMoveY
EndIf
If KeyDown(KEY_LEFT) Then
fMoveX = fMoveX - 1
fScrollX = fPlayerX - fMoveX
EndIf
If KeyDown(KEY_RIGHT) Then
fMoveX = fMoveX + 1
fScrollX = fPlayerX - fMoveX
EndIf

' If fScrollX < 0 Then fScrollX = 0
' If fScrollX > GraphicsWidth() Then fScrollX = GraphicsWidth()
' If fScrollY < 0 Then fScrollY = 0
' If fScrollY > GraphicsHeight() Then fScrollY = GraphicsHeight()



For Local iMapXIndex:Int = 0 To (iMapwidth - 1)
For Local iMapYIndex:Int = 0 To (iMapheight - 1)
If (iMapXIndex - fScrollX) <= (iMapwidth - 1) And (iMapXIndex - fScrollX) >= 0 Then
If (iMapYIndex - fScrollY) <= (iMapheight - 1) And (iMapYIndex - fScrollY) >= 0 Then

DrawImage(tiTiles, iMapXIndex * iTilesize - fScrollX, iMapYIndex * iTilesize - fScrollY, iMap[iMapXIndex - fScrollX, iMapYIndex - fScrollY, 1])

EndIf
EndIf
Next
Next
Flip 0
Wend


Das was auskommentiert ist hat nicht richtig funktioniert, war aber so ne kurze Überlegung.

Wäre echt toll, wenn mir das jemand irgendwie erklären könnte.

Lg, M0rgenstern

Shinkiro1

ehemals "Espada"

BeitragMi, Apr 07, 2010 13:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Hier ein kleiner Auszug meines Projektes, wo das recht gut läuft.

BlitzMax: [AUSKLAPPEN]
        '======================================================================
' Update Cam
'======================================================================
cam_x:+Self.GetSpeedX()
Self.SetX( Self.GetX() + Self.GetSpeedX() )
If cam_x > (map.width*32 - SCREEN_WIDTH)
cam_x:-Self.GetSpeedX()
Self.SetX( Self.GetX() - Self.GetSpeedX()/3 )
EndIf



'==========================================================================
' Render Player to Screen
'==========================================================================
Method Render()
If cam_x <= 0
DrawImage Self.GetImage(), Self.GetX(), Self.GetY()
ElseIf Self.GetX() > map.width*32 - SCREEN_WIDTH + 96
DrawImage Self.GetImage(), (Self.GetX() - map.width*32 + SCREEN_WIDTH), Self.GetY()
Else
DrawImage Self.GetImage(), 96 , Self.GetY()
EndIf
EndMethod


Bei mir ist der Spieler allerdings 96 Pixel vom linken Rand entfernt, also nicht in der Mitte (aber das ist ja leicht anpassbar).
Die cam_x variable kommt bei mir also nur beim Rendern vor, wo sie überprüft wo der Spieler ist. Dessen Koordinaten werden dann relativ zum Bildschirm ausgerechnet und an DrawImage übergeben.

Ich hoffe das konnte dir ein wenig weiter helfen.
Blog :: Ein RPG in 3 Monaten erstellen
Twitter :: News zum Projekt

M0rgenstern

BeitragMi, Apr 07, 2010 13:37
Antworten mit Zitat
Benutzer-Profile anzeigen
ALso, tut mir leid, aber ich muss ehrlich sagen, dass dein Code mir nicht besonders weiterhilft.
Ich weiß ja auch nicht wirklich was genau bei meinem falsch ist.

Lg, M0rgenstern

Xeres

Moderator

BeitragMi, Apr 07, 2010 13:50
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich würde die Spieler- (oder Kamera-) Position am Anfang = 0 setzen und statisch auf die Mitte des Bildschirms Zeichnen. Wenn man sich bewegt, wird die Position normal verändert. Jedes Objekt wird an seine Eigenen Koordinaten + SpielerKoordinaten gezeichnet - vorteilhafter Weise, wenn sie im sichtbaren Bereich liegen.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

M0rgenstern

BeitragMi, Apr 07, 2010 13:53
Antworten mit Zitat
Benutzer-Profile anzeigen
Die Koordinaten auf 0 setzen aber dann auf die Mitte des Schirms zeichnen?
Wie das denn?

Kannst du mir vielleicht ein konkretes Zahlenbeispiel geben? Ich kann mir sowas dann besser vorstellen.
Btw: Brauch ich dann nur noch 4 Variablen? (PlayerX,PlayerY,SCrollX,SCrollY)

Lg, M0rgenstern

Xeres

Moderator

BeitragMi, Apr 07, 2010 14:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Beispiel
BlitzMax: [AUSKLAPPEN]
SuperStrict

AppTitle = "Beispiel"
Graphics(800, 600, 0, 60)
Global gwidth:Float = GraphicsWidth(), gfx_w2:Float = gwidth / 2.0
Global gheight:Float = GraphicsHeight(), gfx_h2:Float = gheight / 2.0

SeedRnd MilliSecs()
Local timer:TTimer = TTimer.Create(60)

AutoMidHandle(True)
SetColor(255, 255, 255)
SetClsColor(255, 255, 255)
SetBlend(AlphaBlend)

Global PlayerX:Float, PlayerY:Float

Repeat
Cls

'* Spieler befindet sich immer in der Mitte...
DrawOval(gfx_w2 - 16, gfx_h2 - 16, 32, 32)
'* Die Umgebung wird um ihn herum verschoben:
If KeyDown(KEY_LEFT) Then PlayerX:+1
If KeyDown(KEY_RIGHT) Then PlayerX:-1
If KeyDown(KEY_UP) Then PlayerY:+1
If KeyDown(KEY_DOWN) Then PlayerY:-1

SetColor(0, 0, 0) ; SetRotation(0)
DrawText("Pos: " + PlayerX + " / " + PlayerY, 10, 10)

'*** GraphicsWidth()/2 Verschiebt den NullPunkt auf die Mitte des Schirms, sonst wäre er (wie sonst) oben Links!
DrawText("0/0", gfx_w2 + PlayerX, gfx_h2 + PlayerY)

Flip(0)
timer.Wait()
If KeyHit(KEY_ESCAPE) Or AppTerminate() Then End
Forever
End


Du musst dann nur noch berechnen, welche Tiles sichtbar sind und gezeichnet werden müssen.
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus
T
HERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld)

Goodjee

BeitragMi, Apr 07, 2010 14:00
Antworten mit Zitat
Benutzer-Profile anzeigen
Code: [AUSKLAPPEN]
fMoveY = fMoveY - 1
fScrollY = fPlayerY - halbeauflösungy



so sollte es eg gehn, der player ist dann ja immer bei halbeauslösung einzumalen
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

M0rgenstern

BeitragMi, Apr 07, 2010 18:11
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey Vielen Dank. Das Prinzip habe ich verstanden.
Ich hätte nur noch eine Frage: Wie beziehe ich ein Offset mit ein.
Ich hab nämlich am Anfang folgendes stehen:

BlitzMax: [AUSKLAPPEN]
Global fPlayerX:Float = iMapwidth / 2
Global fPlayerY:Float = iMapheight / 2


Und dadurch liegt der Spieler erstmal außerhalb der Map.
Ich wollte ihn aber auf die Mitte der Map setzen.


Außerdem habe ich noch ein Problem:
Wenn ich nach rechts und nach unten scrolle, dann wird mit zunehmender zurückgelegter Strecke ein schwarzer Streifen oben bzw unten gebildet, der immer größer wird desto weiter ich scrolle.
Verstehe aber leider nicht ow der herkommt.

Hier mal die Hauptschleife:

BlitzMax: [AUSKLAPPEN]
While Not KeyHit(KEY_ESCAPE) Or AppTerminate()
WaitTimer(FTimer)
Cls

If KeyDown(KEY_UP) Then
fPlayerY:+1
If fPlayerY > iMapheight Then fPlayerY = iMapheight
EndIf
If KeyDown(KEY_DOWN) Then fPlayerY:-1
If KeyDown(KEY_LEFT) Then fPlayerX:+1
If KeyDown(KEY_RIGHT) Then fPlayerX:-1



For Local iMapXIndex:Int = 0 To (iMapwidth - 1)
For Local iMapYIndex:Int = 0 To (iMapheight - 1)

If (iMapXIndex - fPlayerX) <= (iMapwidth - 1) And (iMapXIndex - fPlayerX) >= 0 Then
If (iMapYIndex - fPlayerY) <= (iMapheight - 1) And (iMapYIndex - fPlayerY) >= 0 Then
DrawImage(tiTiles, iMapXIndex * iTilesize - fPlayerX, iMapYIndex * iTilesize - fPlayerY, iMap[iMapXIndex - fPlayerX, iMapYIndex - fPlayerY, 1])
EndIf
EndIf
Next
Next

DrawOval(fGFXWidthHalf - iTilesize, fGFXHeightHalf - iTilesize, iTilesize, iTilesize)

DrawText("Playerpos: " + fPlayerX + " / " + fPlayerY, 30, 30)
DrawText("0/0", fGFXWidthHalf + fPlayerX, fGFXHeightHalf + fPlayerY)
Flip 0
Wend


Lg, M0rgenstern

Goodjee

BeitragMi, Apr 07, 2010 18:26
Antworten mit Zitat
Benutzer-Profile anzeigen
irgendwie komisch was du das tust...für das scrolling solltest du eg den scrollx scrolly wert abziehen nicht fPlayerX fPlayerY

kleines beispiel


BlitzMax: [AUSKLAPPEN]
Graphics 640,480
Global scrollx:Int, scrolly:Int 'scrollwert oder kameraposition
Global playerx:Int,playery:Int

Repeat
Cls
'map gescrollt malen, dh um die kameraposition verschoben
For Local x:Int=0 To 31
For Local y:Int=0 To 31
SetColor(255,255,255)
If((x+y)Mod 2=0) SetColor(128,128,128)
DrawRect x*32-scrollx,y*32-scrolly,32,32
Next
Next
SetColor 255,0,0
DrawOval playerx-16-scrollx,playery-16-scrolly,32,32

'camera neu berechen, hier findet das eigentliche scrolling statt
scrollx=playerx-320
scrolly=playery-240

'player bewegen
playerx:+KeyDown(KEY_RIGHT)-KeyDown(KEY_LEFT)
playery:+KeyDown(KEY_DOWN)-KeyDown(KEY_UP)
Flip
Until KeyHit(KEY_ESCAPE)
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

M0rgenstern

BeitragMi, Apr 07, 2010 19:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Also, ich hab meinen Code jetzt mal angepasst.
Aber das funktioniert jetzt gar nicht mehr. Ich sehe nur noch den weißen Spielerkreis, wenn ich Scrolle den Text "0/0", aber keine Map mehr.
Ich hab hier mal den Code:

BlitzMax: [AUSKLAPPEN]
While Not KeyHit(KEY_ESCAPE) Or AppTerminate()
WaitTimer(FTimer)
Cls

fScrollX = fPlayerX - fGFXWidthHalf
fScrollY = fPlayerY - fGFXHeightHalf


If KeyDown(KEY_UP) Then fPlayerY:+1
If KeyDown(KEY_DOWN) Then fPlayerY:-1
If KeyDown(KEY_LEFT) Then fPlayerX:+1
If KeyDown(KEY_RIGHT) Then fPlayerX:-1



For Local iMapXIndex:Int = 0 To (iMapwidth - 1)
For Local iMapYIndex:Int = 0 To (iMapheight - 1)

If (iMapXIndex - fScrollX) <= (iMapwidth - 1) And (iMapXIndex - fScrollX) >= 0 Then
If (iMapYIndex - fScrollY) <= (iMapheight - 1) And (iMapYIndex - fScrollY) >= 0 Then
DrawImage(tiTiles, iMapXIndex * iTilesize - fScrollX, iMapYIndex * iTilesize - fScrollY, iMap[iMapXIndex - fScrollX, iMapYIndex - fscrolly, 1])
EndIf
EndIf
Next
Next

DrawOval(fPlayerX - iTilesize - fScrollX, fPlayerY - iTilesize - fScrollY, iTilesize, iTilesize)

DrawText("Playerpos: " + fPlayerX + " / " + fPlayerY, 30, 30)
DrawText("0/0", fGFXWidthHalf + fScrollX, fGFXHeightHalf + fScrollY)
Flip 0
Wend


Lg, M0rgenstern

Goodjee

BeitragMi, Apr 07, 2010 19:35
Antworten mit Zitat
Benutzer-Profile anzeigen
die ifbedingungen in der mapmalschleife sind daran schuld, da hat das scrollx/y nichts zu suchen, sobald du die -scrollx und -scrolly raushaust läufts
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

M0rgenstern

BeitragMi, Apr 07, 2010 20:07
Antworten mit Zitat
Benutzer-Profile anzeigen
Also, wenn ich hier:

BlitzMax: [AUSKLAPPEN]
DrawImage(tiTiles, iMapXIndex * iTilesize - fScrollX, iMapYIndex * iTilesize - fScrollY, iMap[iMapXIndex - fScrollX, iMapYIndex - fscrolly, 1])


Das SCrollX und ScrollY rausnehme, dann wird zwar was angezeigt, aber die Map bewegt sicht nicht mehr.
Wenn ichs drin lasse, aber die if-bedingungen davor rausnehme, dann bekomm ich ne Fehlermeldung.

Lg, M0rgenstern

Goodjee

BeitragMi, Apr 07, 2010 20:33
Antworten mit Zitat
Benutzer-Profile anzeigen
moment, ich mache mal...

BlitzMax: [AUSKLAPPEN]

For Local iMapXIndex:Int = 0 To (iMapwidth - 1)
For Local iMapYIndex:Int = 0 To (iMapheight - 1)

If (iMapXIndex) <= (iMapwidth - 1) And (iMapXIndex) >= 0 Then
If (iMapYIndex) <= (iMapheight - 1) And (iMapYIndex) >= 0 Then
DrawImage(tiTiles, iMapXIndex * iTilesize - fScrollX, iMapYIndex * iTilesize - fScrollY, iMap[iMapXIndex,iMapYIndex, 1])
EndIf
EndIf
Next
Next


du musst die map genauso malen wie vorher auch, nur um ein paar pixel verschoben, also die selben bilder nur an anderer stelle
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

M0rgenstern

BeitragMi, Apr 07, 2010 23:12
Antworten mit Zitat
Benutzer-Profile anzeigen
Hey, wow. Vielen Dank. Jetzt funktioneirts und viel wichtiger: Ich habs sogar verstanden.
Vielen Dank.

Ich hätte nur noch eine Frage:
Ich lasse im Moment ein bestimmtes Tilebild am Mauszeiger anzeigen. Also um später dann das entsprechende Tile zu verändern.
Aber wie genau muss ich das jetzt auf die Map umrechnen und wie genau kann ich dann bei einem Mausklick ein Tile ändern? Also eben ein bestimmtes Tile ansprechen?
Ich hab mir sowas gedacht wie: MXTile = (Mousex() + fscrollx) / itilesize
UNd für Höhe entsprechend, bin mir aber nicht sicher...


Lg, M0rgenstern

Alfadur

BeitragMi, Apr 07, 2010 23:35
Antworten mit Zitat
Benutzer-Profile anzeigen
Im Zweifelsfall mal ausprobieren...






...sieht aber richtig aus.

iMapXIndex * iTilesize - fScrollX = X
iMapXIndex * iTilesize = X + fScrollX
iMapXIndex = (X + fScrollX) / iTilesize
A Cray is the only computer that runs an endless loop in less than four hours.

M0rgenstern

BeitragMi, Apr 07, 2010 23:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Ja stimmt auch.
Vielen Dank^^
Sorry für den letzten Post.

Lg, M0rgenstern

Goodjee

BeitragMi, Apr 07, 2010 23:41
Antworten mit Zitat
Benutzer-Profile anzeigen
beim zeichnen machst du folgendes:

malposx=posx-scrollx
malposy=posy-scrolly

beim mausklick machst du dann

posx=malposx+scrollx
posy=malposy+scrolly

malpos ist bei dir halt der mauszeiger
"Ideen sind keine Coladosen, man kann sie nicht recyclen"-Dr. House
http://deeebian.redio.de/ http://goodjee.redio.de/

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Beginners-Corner

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group