Kirjautuminen

Haku

Tehtävät

Koodit: FreeBASIC: ASCII-tasoloikka

Kirjoittaja: TsaTsaTsaa

Kirjoitettu: 17.05.2007 – 28.10.2012

Tagit: grafiikka, ohjelmointitavat, pelinteko, koodi näytille, peli, vinkki

Teinpä tässä tämmöisen hyppelypelin tutustuessani FreeBASIC:iin, en nyt tiedä onko tätä järkeä edes laittaa tänne, mutta kai tästä joku voi jotakin oppia.

Pelin tarkoitus on kerätä kaikki "kolikot" ja sen jälkeen mennä maaliin (symboli G). Kaiken kukkuraksi tiellä on vaarallisia hirviöitä (symboli @), joita pitää varoa. Ukkelia ohjataan nuolilla, hyppää välilyönnillä ja pelistä pääsee pois ESCillä. Ainoa tapa kuolla on mennä itse päin hirviötä. Liikkuminen vähän ankeaa.

Ja testaamiseen tarvitaan kenttätiedosto "1.lvl", esimerkkitiedosto alla. (Kenttä kannattaa ympäröidä seinillä, muuten käy huonosti.)

Testattu Linuxilla FreeBASICin versiolla 0.16b.

' ASCII-tasoloikka
' """"""""""""""""
' Ensimmäinen FreeBASIC-kokeilu. Saa lyödä.
' Sankari liikkuu nuolista, hyppää välilyönnillä, ESC:llä poistuu
'
' Koodilla saa tehdä mitä lystää
'
' TODO: AMPUMINEN

Option Explicit

' ******** FUNKTIOIDEN ESITTELYT ****************
Declare Function LataaTaso (ladattava As String) As Integer
Declare Sub piirraKehys
Declare Sub piirraTaso
Declare Sub piirraMerkki (nro As Integer)
Declare Sub asetaPiirtoReunat
Declare Sub lueNapit
Declare Sub liikutaOlioita
Declare Sub liikutaSankaria (x As Integer, y As Integer)
Declare Sub tulostaTilastot

' Numeroidaan mahdolliset karttaobjektit
Const TYHJA   = 0
Const PELAAJA = 1
Const ESTE    = 2
Const MORKO   = 3
Const KOLIKKO = 4
Const MAALI   = 5


' Alustetaan pelitaso maksimikokoonsa (200*100)
Dim Shared ptaso(199, 99) As Integer
Dim Shared leveys As Integer
Dim Shared korkeus As Integer

' Katsomissuunta (ampumissuunta)
enum Suunta
  VASEN = 1
  OIKEA
End enum

' Otustyyppi (vihollinen/pelaaja)
Type olio
  x As Integer
  y As Integer
  z As Suunta
End Type

' Vihollisista dynaaminen taulukko
Dim Shared viholliset() As olio
Dim Shared sankari As olio        ' pelaaja
Dim Shared kolikkoja As Integer   ' kolikkojen lkm
kolikkoja = 0                     ' aluksi 0

' Kenttätiedosto
Dim taso As String
taso = "1.lvl"

' Ladataan pelitaso
If LataaTaso(taso) = -1 Then
  Print "Tasoa ei saatu ladattua."
  Print "Paina jotakin nappia."
  While INKEY$ = "": WEND
End if

' Piirrettävän tasoalueen reunakoordinaatit ja muutakin
Dim Shared alkuX As Integer, alkuY As Integer
Dim Shared Kaynnissa As Integer
Dim Shared Ilmassa As Integer, hyppyvoima As Integer

Const HYPPYTEHO = 5  ' Tätä säätämällä vaihtuu hypyn korkeus

Ilmassa = 0
Kaynnissa = 1

' Näytön asetus
SCREEN 13

' *** Pääsilmukka ***
Do
  tulostaTilastot
  piirraKehys
  piirraTaso
  lueNapit
  liikutaOlioita
  Sleep 50
Loop until Kaynnissa = 0

CLS
Locate 13, 16
Color 15, 0
Print "Game Over"
While INKEY$ = "": Wend

SCREEN 0
CLS
END


' ********* FUNKTIOIDEN MÄÄRITTELYT *************

' *** Tasonlatausfunktio
Function LataaTaso(ladattava As String) As Integer

  ' Yritetään avata tiedosto
  If Open(ladattava For Input As #1) Then
    LataaTaso = -1   ' Virhepaluuarvo
    Exit Function
  End if

  Dim silmukkaX As Integer, silmukkaY As Integer
  Dim rivi As String, merkit As String

  ' merkit-muuttujaan mahdolliset karttamerkit samassa järjestyksessä, kun ne on numeroitu ylhäällä
  merkit = " X#@oG"

  ' Tyhjätään pelitaso
  For silmukkaX = 0 To 199
    For silmukkaY = 0 To 99
      ptaso(silmukkaX, silmukkaY) = TYHJA
    Next silmukkaY
  Next silmukkaX

  ' Luetaan tiedostosta tason koko
  Input #1, leveys, korkeus

  ' Käydään lopputiedosto läpi rivi kerrallaan
  For silmukkaY = 0 To (korkeus - 1)
    Line Input #1, rivi

    ' Tarkistetaan, että rivillä oikea määrä merkkejä
    If Len(rivi) <> leveys Then
      LataaTaso = -1
      Exit Function
    End If

    For silmukkaX = 0 To (leveys - 1)
      ptaso(silmukkaX, silmukkaY) = InStr(merkit, Mid(rivi, silmukkaX+1, 1)) - 1
      ' Onko vihollinen/pelaaja/kolikko
      If ptaso(silmukkaX, silmukkaY) = MORKO Then
        ' Kasvatetaan vihollistaulukkoa yhdellä ja asetetaan koordinaatit
        Redim Preserve viholliset(1 To (Ubound(viholliset, 1) + 1))
        viholliset(Ubound(viholliset, 1)).x = silmukkaX
        viholliset(Ubound(viholliset, 1)).y = silmukkaY
        viholliset(Ubound(viholliset, 1)).z = VASEN
      Elseif ptaso(silmukkaX, silmukkaY) = PELAAJA Then
        sankari.x = silmukkaX
        sankari.y = silmukkaY
        sankari.z = VASEN
        ' Tason piirtoreunat kuntoon
        asetaPiirtoreunat
      Elseif ptaso(silmukkaX, silmukkaY) = KOLIKKO Then
        kolikkoja = kolikkoja + 1
      End If
    Next silmukkaX
  Next silmukkaY

  ' Suljetaan tiedosto
  Close #1

  ' Kaikki sujui, palautetaan 0
  LataaTaso = 0

End Function


' *** Kentän reunojen piirto
Sub piirraKehys
  Dim i As Integer, j As Integer
  ' Värin vaihto
  Color 8, 0
  ' Ylä- ja alareunat
  For i = 3 To 24 Step 21
    For j = 2 To 39
      Locate i, j
      Print CHR$(219)
    Next j
  Next i
  ' Sivut
  For i = 2 To 39 Step 37
    For j = 3 To 24
      Locate j, i
      Print CHR$(219)
    Next j
  Next i
End Sub


' *** Tason piirto
Sub piirraTaso
  Dim i As Integer, j As Integer
  ' Ruutuun mahtuu tasosta 36x20 kokoinen pala
  ' joten pitää tehdä pieniä tarkasteluita
  If leveys > 36 Then
    For i = 0 To 35
      If korkeus > 20 Then
        For j = 0 To 19
          Locate 4+j, 3+i
          piirraMerkki( ptaso(alkuX+i, alkuY+j) )
        Next j
      Else
        For j = 0 To korkeus - 1
          Locate 4+j, 3+i
          piirraMerkki( ptaso(alkuX+i, j) )
        Next j
      End If
    Next i
  Else
    For i = 0 To leveys - 1
      If korkeus > 20 Then
        For j = 0 To 19
          Locate 4+j, 3+i
          piirraMerkki( ptaso(i, alkuY+j) )
        Next j
      Else
        For j = 0 To korkeus - 1
          Locate 4+j, 3+i
          piirraMerkki( ptaso(i, j) )
        Next j
      End If
    Next i
  End If
End Sub


' *** Apualiohjelma tason piirron selkeyttämiseksi
Sub piirraMerkki(nro As Integer)
  Select Case nro
    Case TYHJA
      Print " "
    Case PELAAJA
      Color 12, 0
      Print "X"
    Case ESTE
      Color 6, 0
      Print "#"
    Case MORKO
      Color 13, 0
      Print "@"
    Case KOLIKKO
      Color 14, 0
      Print "o"
    Case MAALI
      Color 11, 0
      Print "G"
  End Select
End Sub


' *** Piirtoalueen reunojen asetus
Sub asetaPiirtoReunat
  ' Ensin piirtoalueen vasen raja
  If leveys > 36 And sankari.x > 17 Then
    If (leveys - sankari.x) > 18 Then
      alkuX = sankari.x - 17
    Else
      alkuX = leveys - 36
    End If
  Else
    alkuX = 0
  End If
  ' Sitten yläraja
  If korkeus > 20 And sankari.y > 18 Then
    If (korkeus - sankari.y) > 3 Then
      alkuY = sankari.y - 17
    Else
      alkuY = korkeus - 20
    End If
  Else
    alkuY = 0
  End If
End Sub


' *** Näppiksen käsittely
Sub lueNapit
  Dim uusiX As Integer, uusiY As Integer
  uusiX = sankari.x: uusiY = sankari.y
  Select Case INKEY$
    Case CHR$(255) + "K"       ' Vasen
      uusiX = sankari.x - 1
    Case CHR$(255) + "M"       ' Oikea
      uusiX = sankari.x + 1
    Case CHR$(32)              ' Välilyönti
      If Ilmassa = 0 Then
        hyppyvoima = HYPPYTEHO
        Ilmassa = 1
      End If
    Case CHR$(27)              ' ESC
      Kaynnissa = 0
  End Select
  liikutaSankaria(uusiX, uusiY)
End Sub


' *** Hirviöiden liikuttelu
Sub liikutaOlioita
  ' Käydään hirviötaulukko läpi
  Dim i As Integer
  For i = LBound(viholliset,1) To UBound(viholliset,1)
    ' Mihin suuntaan menossa
    Select Case viholliset(i).z
      Case VASEN
        ' Voiko liikkua vasemmalle (eli onko edessä seinä tai joutuuko ilman päälle)
        If ptaso(viholliset(i).x-1, viholliset(i).y) = TYHJA And ptaso(viholliset(i).x-1, viholliset(i).y+1) = ESTE Then
          ptaso(viholliset(i).x, viholliset(i).y) = TYHJA
          viholliset(i).x = viholliset(i).x - 1
          ptaso(viholliset(i).x, viholliset(i).y) = MORKO
        Else  ' Jos ei voi, vaihdetaan suuntaa
          viholliset(i).z = OIKEA
        End If
      Case OIKEA
        ' Voiko liikkua oikealle (eli onko edessä seinä tai joutuuko ilman päälle)
        If ptaso(viholliset(i).x+1, viholliset(i).y) = TYHJA And ptaso(viholliset(i).x+1, viholliset(i).y+1) = ESTE Then
          ptaso(viholliset(i).x, viholliset(i).y) = TYHJA
          viholliset(i).x = viholliset(i).x + 1
          ptaso(viholliset(i).x, viholliset(i).y) = MORKO
        Else  ' Jos ei voi, vaihdetaan suuntaa
          viholliset(i).z = VASEN
        End If
    End Select
  Next i
End Sub


' *** Sankarin liikuttelu tiettyyn kohtaan
Sub liikutaSankaria(x As Integer, y As Integer)
  ' Jos ollaan ilmassa, tehdään temppuja
  If Ilmassa = 1 Then
    If hyppyvoima > 0 Then
      y = y - 1
      hyppyvoima = hyppyvoima - 1
    Else
      y = y + 1
    End If
  End If

  ' Katsotaan, onko tyhjä tai kolikollinen ruutu
  If ptaso(x, y) = TYHJA Or ptaso(x, y) = KOLIKKO Then
    ' Kolikko pois
    If ptaso(x, y) = KOLIKKO Then
      kolikkoja = kolikkoja - 1
    End If
    ' Vanhasta kohtaa sankari pois
    ptaso(sankari.x, sankari.y) = TYHJA
    ' Uudet koordinaatit ja sankari paikoilleen
    sankari.x = x
    sankari.y = y
    ptaso(x, y) = PELAAJA
    ' Uudet piirtoreunat
    asetaPiirtoReunat
    ' Tarkistetaan, ollaanko ilman päällä
    If ptaso(x, y+1) = TYHJA Then
      Ilmassa = 1
    Else
      Ilmassa = 0
    End If

  ' Katsotaan, onko ruudussa mörkö
  Elseif ptaso(x, y) = MORKO Then
    ' Peli loppuu :(
    Kaynnissa = 0
  ' Onko maali?
  Elseif ptaso(x, y) = MAALI Then
    ' Onko kolikot kerätty
    If kolikkoja = 0 Then
      Kaynnissa = 0
    End If
  End If
End Sub

' *** Tilastojen tulostusta
Sub tulostaTilastot
  Locate 1, 2: CLS
  Color 15, 0
  Print "Kolikkoja:";
  Print kolikkoja
End Sub

kenttätiedosto 1.lvl

40 30
########################################
#         #                            #
#G        # o              o         o #
######    #########      ####       ####
#                 #                    #
#      @          #                    #
#############     ####            ## o #
#                    ##          ###   #
#                    ###        ####   #
# o   #   #          ####      #####   #
#######   #######    #####    ######   #
#                                      #
# o              @                     #
#######   ################    ##########
#            o                         #
#                      #       @    o  #
#                      #################
#     #############                    #
#     #         o #                    #
#  o  #        ###################     #
#######           #       #  o  #      #
#                             @        #
# o       ##############################
#####     #o                           #
#o        #                            #
#         #            @               #
#     #######     ##############       #
#                        #             #
#                      o #         X   #
########################################

Kommentit

Antti Laaksonen [18.05.2007 22:11:09]

#

Mitenköhän tuon liikkumisen saisi vähän sujuvammaksi? Nimittäin muuten koossa on varsin hyvä pelin runko.

Dude [19.05.2007 12:48:34]

#

Mä koitin kääntää windows versiolla niin jos muutti hypyn tehoa seiskaan niin kääntäjä valitti jotain. Oli kyllä ihan hyvä ja se liikkuminen tosiaan toimii huonosti. Liian nopea jopa tällä 366mhz koneella.

moptim [19.05.2007 20:28:58]

#

Kääntyisköhän tuo KuikPeisikillä?

T.M. [19.05.2007 22:01:09]

#

Ei todellakaan.

hejppa [20.05.2007 20:25:06]

#

Kääntyisköhän toi GCC:llä?!?

Gwaur [21.05.2007 01:30:53]

#

Ei, koska GCC ei sisällä FreeBASIC-kääntäjää.

E.K.Virtanen [21.05.2007 07:39:54]

#

Työkoneella ei ole FB kääntäjää mutta mitä sorsaa tässä katselin niin...
Sleep 50 voisi vaihtaa Sleep 100, 1 niin peli ei olisi niin nopea.
, 1 perässä muuttaa niin että peli odottaa aina sen 100ms välittämättä siitä painaako pelaaja nappulaa vai ei.
Normaalistihan Sleep odottaa annetun ajan tai kunnes nappulaa painetaan.

INKEY$ lukeminen suoraan voi joskus kököttää joten...

Sub lueNapit
  Dim uusiX As Integer, uusiY As Integer
  Dim Namiska AS String
  uusiX = sankari.x: uusiY = sankari.y

  Namiska = INKEY$
  Select Case Namiska

Lisäksi, jos näytöllä oleva taso ei vaihdu niin kannattaisi piirtää uudelleen vain ne asiat jotka liikkuvat. Eli normaalisti vain sankari ja möröt.

Pitääpä kopioida tuo usb:lle kun kotona vieläkään netti auki ja kokeilla. Ihan kivalta pikku peliltä vaikuttaa.

MikSor [31.05.2007 13:00:09]

#

Todella uskomaton homma!

rautamiekka [20.06.2007 19:37:28]

#

Offtopic-kysymys: mikä on FreeBASIC ?

Are0100 [27.06.2007 10:30:06]

#

öö?? miten tuosta oiken tehdään pelattava? voisko joku lattaa neuvot?

E.K.Virtanen [03.07.2007 11:37:45]

#

@Are0100: Lataa fb kääntäjä osoitteesta www.freebasic.net
Tallenna ylläolevat filut ja kirjoita fbc filenimi.bas ja käynnistä.

nomic [14.07.2007 13:00:07]

#

oikein mukava, vaikka ei tule freebasicia käytettyä pahemmin. :)

Dude [01.08.2007 15:58:44]

#

mä voisin muokata sitä mun qb kenttäeditoria niin että toimis tuolla.
Käänsin tuon pelin qbeelle.

lobodomy [10.12.2008 16:18:01]

#

Hienolta vaikuttaa mutta mihin toi kenttä olis tarkotus laittaa?
Ainiin Option Explicit aiheuttaa errorin.

Kirjoita kommentti

Muista lukea kirjoitusohjeet.
Tietoa sivustosta