CoolBasic oppitunti 19: Painovoima, versio 2.0

Oletko tehnyt jotain, mistä muut voisivat hyötyä. Postita vinkit tänne.
Post Reply
SPuntte
Tech Developer
Tech Developer
Posts: 650
Joined: Mon Aug 27, 2007 9:51 pm
Location: Helsinki, Finland
Contact:

CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by SPuntte »

Jostain tipahti ajatus CB:n painovoimaesimerkistä vähän paremman tuntuisella fysiikalla. Siispä oppitunti nro 19 auki ja modaus käyntiin. Ja tässä tulos kaikkien iloksi:

Code: Select all

SCREEN 480,320,0,1
SetWindow "Painovoimaesimerkki "+Chr(34)+"parannetulla"+Chr(34)+" fysiikkamallinnuksella by SPuntte - © 2010"

//Rajoitetaan ruudunpäivitystaajuutta
Const maksimiFPS = 50
FrameLimit maksimiFPS

//==========================================================================================
//KOKEILE LEIKKIÄ NÄILLÄ

Dim painovoima#, painovoima2#
painovoima = 700.0					//Painovoiman suuruus vaikuttaa pelihahmon hyppykorkeuteen, sekä siihen, miten pitkään hyppy kestää.
painovoima2 = 400.0					//Säätää hyppynäppäimen pohjassa pitämisen vaikutusta hyppykorkeuteen.

Dim hyppyviive% As Integer
hyppyviive = 800					//Aika millisekunteina, jonka jälkeen hyppynäppäimen pohjassa pitäminen ei enää vaikuta hypyn korkeuteen.

Dim vastusMaa#, hyppyimpulssi#, juoksuvoima#, lentokerroin#, massa#, ilmanvastuskerroin, kimmokerroin#, hyvinPieniNopeus# As Float
vastusMaa = 0.05					//Kitka, joka vaikuttaa, kun pelihahmon on maassa eikä juokse.
hyppyimpulssi = 400.0/maksimiFPS	//Impulssi (liikemäärä), jonka pelihahmo saa hypätessään.
juoksuvoima = 650.0					//Määrää pelihahmon suurimman nopeuden yhdessä ilmanvastuskertoimen kanssa.
lentokerroin = 0.5					//Juoksuvoiman kerroin, kun pelihahmo ON ilmassa. 0 -> realistinen; liikettä ei voi muuttaa ilmassa
massa = 1.3 						//Pelihahmon massa. Suurempi massa vähentää juoksuvoiman, ilmanvastuksen ja hyppyimpulssin vaikutusta.
ilmanvastuskerroin = 28.0			//Vaikuttaa sekä pelihahmon maksiminopeuteen sekä siihen, miten pitkälle pelihahmo liikkuu juoksemisen lopetettuaan.
kimmokerroin = 0.4					//Kuinka paljon pelaajan liike-energiasta säilyy törmättäessä kattoon.
hyvinPieniNopeus = 0.05				//Mikäli pelihahmon nopeus laskee alle tämän, sen katsotaan pysähtyneen
//==========================================================================================

'lataa kartta, siirrä sitä ylöspäin ja animoi se.
Dim kentta
kentta=LoadMap("Media\testmap.til","Media\tileset.bmp")
PositionObject kentta,0,50
PlayObject kentta,0,0,0.5

'lataa animaatiosarja oikealle, maskaa ja piilota se
Dim oikea
oikea=LoadAnimObject("Media\zerorun1.bmp",47,51,0,13)
MaskObject oikea,cbMagenta
ShowObject oikea,OFF
ObjectRange oikea,30,51 'tämä pitää asettaa kaikkiin

'sama vasemmalle
Dim vasen
vasen=LoadAnimObject("Media\zerorun2.bmp",47,51,0,13)
MaskObject vasen,cbMagenta
ShowObject vasen,OFF
ObjectRange vasen,30,51 'tämä pitää asettaa kaikkiin

'Tämä on varsinainen pelihahmo, joka piirretään ja
'jota hallitaan. Sille asetetaan törmäys->kartta
'Tätä EI PIILOTETA.
Dim pelihahmo
pelihahmo=CloneObject(oikea)
SetupCollision pelihahmo,kentta,1,4,2
ObjectRange pelihahmo,30,51 'tämä pitää asettaa kaikkiin

//Muuttujat hahmon nykyiselle ja edelliselle sijainnille
Dim hahmoX#, hahmoY#, vanhaX#, vanhaY# As Float
hahmoX = ObjectX(pelihahmo)
hahmoY = ObjectY(pelihahmo)
vanhaX = hahmoX
vanhaY = hahmoY

'-------------------------------------------------
'Pääsilmukka
Repeat
	//Nollataan pelaajaan vaikuttavat voimat varmuuden vuoksi
	Dim voimaX#, voimaY#
	voimaX# = 0
	voimaY# = 0
	
	Dim maassa% As Integer
	Dim kitka# As Float
	Dim nopeusX#, nopeusY# As Float	//Pelihahmon nykyisen ja edellisen sijainnin erotus
	
	//-----------------------------------------------------------------------------------------
	//PELIHAHMON KONTROLLOINTI
	
	If RightKey() Then 
		'juokse oikealle
		PaintObject pelihahmo,oikea 'vaihda kuvaa...
		If maassa Then PlayObject pelihahmo,2,11,0.25
		//Kiihdytetään oikealle (>0)
		voimaX = juoksuvoima
	ElseIf LeftKey() Then
		'juokse vasemmalle
		PaintObject pelihahmo,vasen 'vaihda kuvaa...
		If maassa Then PlayObject pelihahmo,2,11,0.25
		//Kiihtyvyys vasemmalle (<0)
		voimaX = -juoksuvoima
	Else
		'pysäytä animaatio, jos ei juosta
		PlayObject pelihahmo,0
	EndIf
	//Säädetään ilmanvastusta, jos ilmassa
	If Not maassa Then voimaX = voimaX * lentokerroin
	//Jos ei juosta ja ollaan maassa, hidastetaan pelihahmoa kitkalla
	If maassa And voimaX = 0 Then
		kitka = vastusMaa
	Else
		kitka = 0
	EndIf
	
	//Ilmanvastus vaikuttaa pelihahmon liikesuuntaa vastaan ja ainoastaan, jos nopeus <> 0
	If Abs(nopeusX) > hyvinPieniNopeus Then
		voimaX = voimaX -((nopeusX)/Abs(nopeusX))*ilmanvastuskerroin*(nopeusX)*(nopeusX)
	Else
		nopeusX = 0
		vanhaX = hahmoX
	EndIf
	
	//-----------------------------------------------------------------------------------------
	//HYPPY
	
	Dim hyppyajastin% As Integer
	If KeyHit(cbKeyUp) And maassa Then 
		hyppyajastin = Timer()	//Hypyn ajankohtaa tarvitaan myöhemmin
		vanhaY = hahmoY - (hyppyimpulssi/massa) //Annetaan pelaajalle impulssi ylöspäin
		voimaY = -painovoima2
	EndIf
	//Tässä vaikutetaan hypyn korkeuteen.
	If KeyDown(cbKeyUp) And (Not maassa) And Timer() - hyppyajastin <= hyppyviive Then
		voimaY = -painovoima2
	Else
		voimaY = -painovoima
	EndIf
	
	//-----------------------------------------------------------------------------------------
	//PELIHAHMON PÄIVITYS
	
	Dim tmpX#, tmpY#
	//Lasketaan (itse asiassa Verlet-integroidaan :P) pelaajalle uusi paikka
	tmpX = (2-kitka)*hahmoX - (1-kitka)*vanhaX + voimaX/massa*(1.0/maksimiFPS)*(1.0/maksimiFPS)
	tmpY = (2-kitka)*hahmoY - (1-kitka)*vanhaY + voimaY/massa*(1.0/maksimiFPS)*(1.0/maksimiFPS)
	vanhaX = hahmoX
	vanhaY = hahmoY
	hahmoX = tmpX
	hahmoY = tmpY
	
	//lasketaan uusi nopeus objektin liikuttamista varten
	nopeusX = hahmoX - vanhaX
	nopeusY = hahmoY - vanhaY
	'liikuta pelihahmoa
	TranslateObject pelihahmo,(nopeusX),(nopeusY)
	
	UpdateGame 'päivitä törmäys
	CloneCameraPosition pelihahmo 'liimaa kamera

	//Mikäli törmäys tapahtui, hahmo ei ehkä siirtynyt sinne, minne fysiikka sitä yritti siirtää
	//-> päivitetään varmuuden vuoksi, jotta fysiikka ja todellinen sijainti pysyvät synkassa
	hahmoX = ObjectX(pelihahmo)
	hahmoY = ObjectY(pelihahmo)
	
	//-----------------------------------------------------------------------------------------
	//TÖRMÄYSTEN TUNNISTUS JA KÄSITELY
	
	maassa=0 'ilmassa jollei toisin käy ilmi
	Dim tormaykset% As Integer
	tormaykset=CountCollisions(pelihahmo)
	'katsotaan tärmätäänkö kattoon tai lattiaan
	Dim i% As Integer
	For i=1 To tormaykset
		If GetCollision(pelihahmo,i)=kentta
			Dim tKulma%
			tKulma = CollisionAngle(pelihahmo,i)//Törmäyskulma talteen, ettei tule turhia funktiokutsuja
			'lattia
			If tKulma=90 Then 
				maassa=1 'jalat ON maassa
			//seinät
			ElseIf tKulma = 0 Or tKulma = 180 Then
				vanhaX = hahmoX + kimmokerroin*(nopeusX)
			'katto
			ElseIf tKulma=270 Then 
				vanhaY = hahmoY + kimmokerroin*(nopeusY)
			EndIf
		EndIf
	Next i 
	   
	'jos ollaan ilmassa, näytä toisenlainen kuva
	If Not maassa Then PlayObject pelihahmo,12,0

	DrawGame //Objektit täytyy piirtää, jotta teksti näkyy
	Text 5, 5, "FPS: " + FPS()
	
	DrawScreen 'piirrä näyttö

Until EscapeKey()
Huomioita koodista:
Koodi näyttää hirveältä siksi, että se on tosiaan vain vähän reilummalla kädellä muokattu versio alkuperäisestä oppitunnista, ja sen sisällöstä varmaan puolet on kommenttirivejä. Ajattelin kuitenkin, että siitä on ehkä näin enemmän hyötyä; tyyppikokoelmat ja muut hienostuneemmat koodikoukerot todennäköisesti nostaisivat tutustumiskynnyksen turhan korkeaksi aloittelijoille.

Tämä on esimerkki, ei valmis fysiikkakirjasto. Osaavampi koodari vääntää tästä luonnollisesti geneerisemmän version, jolloin käyttö suuremmilla objektimassoilla on mahdollista. Soveltaminen omiin projekteihin on sallittua ja suositeltavaa ;)

Koodi on Force Variable Declaration -yhteensopivaa, sillä ilman sitä typofixaus olisi täyttä masokismia.

Fysiikasta:
CB:n objektimoottori on parhaimmillaan alkuperäisessä oppituntikoodissa: yksinkertainen mutta silti täysiverinen tasohyppelymoottori on ängetty reilusti alle sataan riviin(ilman kommentteja). Tarkituksenaani olikin näyttää, että pienellä vaivalla siitä saa hiottua timantin. Periaatteesa mitään alkuperäistä ominaisuutta ei ole poistettu - ainoastaan hypyn ja painovoiman toimintaa on hieman säädetty, mutta objektimoottoria hyödynnetään yhä samalla tavalla. Alkuperäisen ohjauksen tilalla on nyt pari matematiikan ja fysiikan kaavaa (ilmanvastus sekä Verlet-integraattori) eikä muuta.

Esimerkissä ei ole haettu realismia, vaikka muuttujia säätämällä sen lisääminen onnistuukin. "Alitajuiseksi esikuvaksi" voisin mainita Messhofin Punishment: The Punishing -pelin.

Simulaation dynamiikka on siinä mielessä FPS-riippumatonta, että mikäli se pyörii asetetulla maksimiruudunpäivitystaajuudella, ei sen toiminnassa ole suurta eroa. Verlet-algoritmin ominaisuus kuitenkin on, että se ennemminkin hukkaa energiaa kuin lisää sitä. Tämä näkyy siten, että matalammalla FPS-rajoituksella pelihahmo liikkuu hieman hitaammin.
EDIT:

@Grandi: suurenna vastusMaa-muuttujan arvoa. Arvo 1.0 poistaa liukumisen kokonaan.

Last edited by SPuntte on Tue Mar 23, 2010 8:11 pm, edited 2 times in total.
CoolBasic henkilökuntaa
Tech-kehittäjä
CoolBasic Classic, Cool VES

CoolPhysicsEngine | MissileSystem | Jana-ympyrä -törmäys | cbSimpleTexture | CoolCPLX
Koodiapina
Forum Veteran
Posts: 2396
Joined: Tue Aug 28, 2007 4:20 pm

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by Koodiapina »

Tyyppi liukuu lattiapinnoilla kuin öljytyllä jäällä, mikä tekee ohjailusta hieman ärsyttävää ja epärealistista. Super Tuxissa on muistaakseni samankaltainen systeemi, joka mielestäni melkeinpä pilaa koko pelin, koska haasteen olisi voinut lisätä muillakin tavoilla. Tosin kyseisessä pelissä liukuminen selittyy juuri sillä, että siinä seikkaillaan jääpintojen päällä.

Mielestäni olisi fysiikan lakien noudattamista tärkeämpää saada miellyttävä pelituntuma. Voi tosin olla, että monet tykkäävätkin tälläisestä ja olen itse vain "vanhoillinen".
Bave-
Newcomer
Posts: 8
Joined: Sat May 15, 2010 5:09 pm
Contact:

Hienoa!

Post by Bave- »

Minusta taas on hyvä, että teit tällaisen lisän 19. oppituntiin.
Vaikka se on kyllä totta, että tässä tuo liukuminen ei tunnu todenmukaiselta.
Olen kyllä itsekin pelannut tuota SuperTux- peliä, mutta mielestäni sellaisiin peleihin tämä liukumistehoste sopii.

Tuosta koodista kyllä se, että siellä on sekaisin erilaisia kommenttimerkkejä. ( ' , // )
Onko sillä jokin tarkoitus?

Mutta minusta tämä oli oikeasti hyvä lisä tuohon oppituntiin, minäkin hyödyin tästä selvennyksestä, koska olen vielä aloitteleva ohjelmoija. :D
Milloin CoolBasic Classic Julkaistaan ?

Huomisen ammattipelintekijä...
Bave-
MaGetzUb
Guru
Posts: 1715
Joined: Sun Sep 09, 2007 12:35 pm
Location: Alavus

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by MaGetzUb »

Bave- wrote:Tuosta koodista kyllä se, että siellä on sekaisin erilaisia kommenttimerkkejä. ( ' , // )
Onko sillä jokin tarkoitus?
Ei. Todennäikösesti SPuntte on tottunut käyttämään // komennti merkkiä, kun taas ' on jäljelle jäännös alkuperäisestä.
Solar Eclipse
Meneillä olevat Projektit:
We're in a simulation, and God is trying to debug us.
phons
Guru
Posts: 1056
Joined: Wed May 14, 2008 10:11 am

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by phons »

Oikeastaan tästä voisi tehdä jopa oman oppitunnin, 21 siis.. Vaikka joku,(nimi siis) fysiikka, matemaattisten operaattoreiden\muutttujien kehittynyt käyttö yms.
Image
Bave-
Newcomer
Posts: 8
Joined: Sat May 15, 2010 5:09 pm
Contact:

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by Bave- »

Niinpä.

Tämähän toimii (kai) myös esim. jos auton laittaa driftaamaan.
Ihan järkevä olisi oppitunniksi 21.
Milloin CoolBasic Classic Julkaistaan ?

Huomisen ammattipelintekijä...
Bave-
User avatar
ItzRaines
Active Member
Posts: 211
Joined: Sat Feb 05, 2011 6:59 pm

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by ItzRaines »

Tuossa pisti silmään, että miksi Framelimit:n on täytynyt tehdä noin vaikeasti? :shock:
Kai olisi riittänyt, kun olisi laittanut vain "Framelimit 50"? :D
Sly_Jack0
Devoted Member
Posts: 612
Joined: Mon Dec 10, 2007 8:25 am

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by Sly_Jack0 »

ItzRaines wrote:Tuossa pisti silmään, että miksi Framelimit:n on täytynyt tehdä noin vaikeasti? :shock:
Kai olisi riittänyt, kun olisi laittanut vain "Framelimit 50"? :D
Koska nyt liikkuminen ei ole fps-riippuvaista, vaan pelaajan liikkeen määrä riippuu yhteen silmukkaan käytetystä ajasta. Vaikka fps tippuisi esim. 30, niin pelaaja liikkuisi siltä yhtä nopeasti.
User avatar
ItzRaines
Active Member
Posts: 211
Joined: Sat Feb 05, 2011 6:59 pm

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by ItzRaines »

Sly_Jack0 wrote:
ItzRaines wrote:Tuossa pisti silmään, että miksi Framelimit:n on täytynyt tehdä noin vaikeasti? :shock:
Kai olisi riittänyt, kun olisi laittanut vain "Framelimit 50"? :D
Koska nyt liikkuminen ei ole fps-riippuvaista, vaan pelaajan liikkeen määrä riippuu yhteen silmukkaan käytetystä ajasta. Vaikka fps tippuisi esim. 30, niin pelaaja liikkuisi siltä yhtä nopeasti.
Täytyypä muistaa tuo vinkki. Enpä tullut ajatelleeksi.
User avatar
esa94
Guru
Posts: 1855
Joined: Tue Sep 04, 2007 5:35 pm

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by esa94 »

Semi-fixed timestep lienee kuitenkin paras ratkaisu; muuten korkeilla frametimeilla pelaaja voi liikkua seinien läpi vahingossa.
User avatar
Ilmuri
Developer
Developer
Posts: 277
Joined: Sun Aug 26, 2007 2:46 pm
Location: \o

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by Ilmuri »

Verlet ei kyllä tykkää alkuunsakkaan vaihtelevasta timestepistä, kts. http://www.lonesock.net/article/verlet.html
CoolBasic henkilökuntaa
Kehittäjä
CoolBasic Classic
User avatar
esa94
Guru
Posts: 1855
Joined: Tue Sep 04, 2007 5:35 pm

Re: CoolBasic oppitunti 19: Painovoima, versio 2.0

Post by esa94 »

Näköjään.

Tietysti tuollaiset esineiden läpi kävelemiset voisi tarkistaa vaikka traceilla.
Post Reply