Kirjautuminen

Haku

Tehtävät

Keskustelu: Koodit: QB: Asteroids

Puhveli [11.03.2005 10:11:35]

#

On muutamia ohjelmia jotka lähes jokainen ohjelmointiharrastaja tulee joskus tekemään: hirsipuu, tekstiseikkailu, lukkarieditori, 3d-moottori ja asteroids-klooni.

Tämä on sellainen pikkuprojekti jonka koodasin koulussa hyppytunnilla. Koodi on aika simppeliä, tästä ei ole mitään uutta, mutta onpahan esimerkki trogonometrian käytöstä objektien liikuttamiseen.

Koulussa on kiva koodata, siellä on niin vähän DOS-muistia niin ohjelmista ei tule turhan pitkiä :) (tai siis mielestäni tämä ei ole kovinkaan pitkä pelin sorsaksi)

Tässä binaarina kun jotkut sitä tuntuvat vonkaavan. Exessä ei kuiteskaan ole hidastusta koska koulussa ei riittäny muisti sen lisäämiseen koodiin :(
http://sooda.dy.fi:8080/mordor/dl/ASTEROID.EXE

'Elikkäs tässä on minun ASTEROIDS-klooni
'ei toimi ihan samoin kuin esikuvansa, sillä vauhtia voi tässä myös hidastaa jne mutta yhteistä on ainakin obstaakkeleiden seassa lentely

'napit on
'ylöös: lisää kaasua
'alaas: vähemmän kaasua
'vasen ja oikea: väistöliikkeet (kääntyminen)
'enter tai space: ampus
'esc: lopetus

DECLARE SUB killasteroid (i!) 'asteroidin räjäytyssubi
DECLARE SUB newasteroid (x!, y!, hor!, ver!, radius!, nodes!, angle!, spin!, lifetime!) 'tekee uuden asteroidin ensimmäiseen vapaaseen asteroidipaikkaan
TYPE asteroidtype
    nodes AS INTEGER 'montako kulmaa
    x AS SINGLE
    y AS SINGLE
    angle AS SINGLE 'mintenkä asteroidi on pyörähtänyt
    hor AS SINGLE 'horisontaalinen liikkumisnopeus
    ver AS SINGLE 'vertikaalinen liikkumisnopeus
    spin AS SINGLE 'pyörimisnopeus
    radius AS SINGLE 'halkaisija pikseleinä
    lifetime AS INTEGER 'jos -1, asteroidi elää kunnes ammutaan, jos > 0 asteroidi elää niin monta framea kuin lifetime määrää (eli kyseessä on asteroidinsirpale, splintteri)
END TYPE

TYPE shottype
    x AS SINGLE
    y AS SINGLE
    angle AS SINGLE 'liikkumissuunta
    speed AS SINGLE
    lifetime AS INTEGER 'kuinka monta framea rojektiili lentelee vielä
END TYPE

'en ole laskenut noita boundeja, mutta niissä on kai reilusti pelivaraa. voi koittaa laskea jos kokee tarpeelliseksi
DIM SHARED asteroid(1 TO 999) AS asteroidtype
DIM SHARED shot(30) AS shottype

CONST factor = 3.141592 / 180

'pls = pelaajan nopeus
'pla = pelaajan liikkumissuunta asteina
'shotdelay = montako frame odotetaan ennen kuin voi ampua uudestaan
'throttle = kaasu (+ / - / off)
'turning = kääntyminen (vasen / oikea / off)
'throttlen ja turningin itseisarvo määrää kuinka monta framea niiden vaikutus kestää

SCREEN 7, , 1, 0 'toinen sivu on aktiivinen, toinen se mikä näytetään (olikohan nimeltään tuplabufferointi?)

'tilastotietoja
DIM SHARED frags AS INTEGER 'tuhottujen asteroidien lkm
DIM SHARED shots AS INTEGER 'ammutut laukaukset

pls = -2 'pelaajan nopeus (negatiivinen vie eteenpäin)
asteroids = 120 'asteroidin lukumäärä alussa
cx = 320 / 2: cy = 200 / 2 'kentän keskikohta

'asteroidien sijoittuminen kartalle
fieldwidth = 1000 'kartan leveys
fieldheight = 1000 'kartan pituus

    'tehdään aloitusasteroidit
    FOR i = 1 TO asteroids
        x = RND * fieldwidth - fieldwidth / 2 + cx
        y = RND * fieldheight - fieldheight / 2 + cy
        r = RND * 10 + 7 'säde
        newasteroid x, y, (RND - .5) / 5, (RND - .5) / 5, r, r * .7, RND * 360, RND * 10 - 5, -1
    NEXT

DIM foo AS STRING 'Foo = viimeksi painettu INKEY$
DO: foo = INKEY$

CLS

    'piirretään pelaajan vesseli ja käännetään sitä pelaajan liikkumiskulman mukaan
    a = (pla - 90) * factor
    x1 = COS(a) * 15 + cx
    y1 = SIN(a) * 15 + cy

    a = (pla + 90) * factor
    x4 = COS(a) * 5 + cx
    y4 = SIN(a) * 5 + cy

    a = (pla + 90 + 45) * factor
    x2 = COS(a) * 15 + cx
    y2 = SIN(a) * 15 + cy

    a = (pla + 90 - 45) * factor
    x3 = COS(a) * 15 + cx
    y3 = SIN(a) * 15 + cy

    LINE (x1, y1)-(x2, y2), 1
    LINE (x2, y2)-(x4, y4), 1
    LINE (x1, y1)-(x3, y3), 1
    LINE (x4, y4)-(x2, y2), 1
    LINE (x4, y4)-(x3, y3), 1

    PAINT (cx, cy), 11, 1

    'lasketaan, kuinka paljon asteroideja täytyy liikuttaa
    '(on simppelinpää tehdä se näin että asteroidit liikkuvat eikä pelaaja)
    a = (pla - 90) * factor
    x = COS(a) * pls
    y = SIN(a) * pls

    'silmukka jokaiselle asteroidille
    FOR i = 1 TO UBOUND(asteroid)
        IF asteroid(i).radius > 0 THEN
            'liikutetaan asteroidia sekä pelaajan että asteroidin nopeuden perusteella
            asteroid(i).x = asteroid(i).x + x + asteroid(i).hor
            asteroid(i).y = asteroid(i).y + y + asteroid(i).ver

            'katotaan ettei asteroid(i).angle ylitä 360 ja käännetään asteroidia
            asteroid(i).angle = asteroid(i).angle MOD 360
            asteroid(i).angle = asteroid(i).angle + asteroid(i).spin

            IF asteroid(i).lifetime > 0 THEN
                asteroid(i).lifetime = asteroid(i).lifetime - 1
                IF asteroid(i).lifetime <= 0 THEN asteroid(i).radius = 0 'hävitetään asteroidinsirpale kun se on riehunut kentällä riittävän kauan
            END IF

            'määrätään asteroideille eri piirtoväri kuin sirpaleille selvyyden vuoksi
            IF asteroid(i).lifetime = -1 THEN fill = 7: border = 8 ELSE fill = 8: border = 1

            'piirretään monikulmio eli asteroidi
            FOR a = asteroid(i).angle TO 360 + asteroid(i).angle STEP 360 / asteroid(i).nodes
                x1 = COS(a * factor) * asteroid(i).radius + asteroid(i).x
                y1 = SIN(a * factor) * asteroid(i).radius + asteroid(i).y

                a2 = a - (360 / asteroid(i).nodes)
                x2 = COS(a2 * factor) * asteroid(i).radius + asteroid(i).x
                y2 = SIN(a2 * factor) * asteroid(i).radius + asteroid(i).y

                LINE (x1, y1)-(x2, y2), border
            NEXT
            'täytetään monikulmio eli asteroidi (omg :p)
            PAINT (asteroid(i).x, asteroid(i).y), fill, border

            'mitataan asteroidin etäisyys pelaajan pythagoraan käskyllä a^2 + b^2 = c^2
            ex = asteroid(i).x - cx: ey = asteroid(i).y - cy
            dist = SQR(ex * ex + (ey * ey))
            IF dist < asteroid(i).radius + 3 AND asteroid(i).lifetime <= 0 THEN killasteroid i: EXIT DO
        END IF
    NEXT

    'silmukka ampuksille
    FOR i = 0 TO UBOUND(shot)
        IF shot(i).lifetime > 0 THEN
            'jotta ammus ei lentelisi loputtomiin vähennetään lifetimeä:
            shot(i).lifetime = shot(i).lifetime - 1
            'liikutetaan ampusta
            a = (shot(i).angle - 90) * factor
            shot(i).x = COS(a) * shot(i).speed + shot(i).x
            shot(i).y = SIN(a) * shot(i).speed + shot(i).y

            'piirretään komea KELTAINEN lasersäde:
            a = (shot(i).angle + 90) * factor
            LINE (shot(i).x, shot(i).y)-(COS(a) * 5 + shot(i).x, SIN(a) * 5 + shot(i).y), 14

            'tarkistetaan mahd. osuma asteroidiin
            FOR d = 1 TO UBOUND(asteroid)
                IF asteroid(d).radius > 0 THEN
                    'jos asteroidi elää, mitataan sen etäisyys ammukseen:
                    ex = asteroid(d).x - shot(i).x: ey = asteroid(d).y - shot(i).y
                    dist = SQR(ex * ex + (ey * ey))
                    'jos osuma, tapetaan asteroidi ja ammus
                    IF dist < asteroid(d).radius AND asteroid(d).lifetime <= 0 THEN
                        killasteroid d 'tuhoa asteroidi
                        shot(i).lifetime = 0 'hävitä ammus
                        exit for 'älä tarkista uusia asteroiditörmäyksiä tälle samalle ammukselle, muuten tämä ammus tuhoaisi killasteroid-subissa syntyvät asteroidinsirpaleet
                    END IF
                END IF
            NEXT
        END IF
    NEXT

    'kiihdytetään (nopeudellisesti) ja käännetään pelaajaa (melkein purkkaa mutta ei ihan)
    'jos throttle != 0, throttlea lähennetään kohti nollaa ja kiihdytetään pelaajan vauhtia (pls on siis pelaajan nopeus)
    IF throttle <> 0 THEN
        throttle = throttle - SGN(throttle)
        pls = pls - SGN(throttle) / 25
    ELSE
        'tämä on kitkaefekti (en tiedä onko validi mutta toimii ja on järkeenkäypä)
        pls = pls - (.0005 * SGN(pls))
        IF ABS(pls) < .0005 THEN pls = 0
    END IF

    'pelaajan kääntäminen toimii samalla tavalla kuin yllä paitsi että kitkavaikutus on otettu pois
    '(tietenkin, muutenhan nokka hakeutuisi kokoajan pohjoiseen, eikä sitä haluta)
    IF turning <> 0 THEN
        turning = turning - SGN(turning)
        pla = pla + SGN(turning) * 5
    END IF

    'napit
    SELECT CASE INP(&H60)
        CASE 75: turning = -2 'vasen
        CASE 72: throttle = 10 'ylös
        CASE 77: turning = 2 'oikea
        CASE 80: throttle = -10 'alas
        CASE 28, 57: 'käysisään tai avaruus
            IF shotdelay <= 0 THEN
                'etsitään eka tyhjä ammus (joka ei ole liikenteessä) ja lähetetään se matkaan
                FOR i = 0 TO UBOUND(shot)
                    IF shot(i).lifetime <= 0 THEN
                        shot(i).lifetime = 32 'ammus lentää 32 frame eli lifetime * speed pikselin matkan
                        shot(i).x = cx
                        shot(i).y = cy
                        shot(i).angle = pla
                        shot(i).speed = 3
                        EXIT FOR
                    END IF
                NEXT
                shotdelay = 5 'milloin voidaan ampua uusiks?
                shots = shots + 1
            END IF
    END SELECT
    IF shotdelay > 0 THEN shotdelay = shotdelay - 1

    'tehdään kuvalle raamit koska muuten PAINT sekoilisi (voit testata miten jos otat 2 riviä alta poies)
    LINE (10, 10)-(309, 189), 1, B
    PAINT (1, 1), 1

    PCOPY 1, 0 'nyt kun piiräminen on valmis, siirretään piirretty kuva näkyviin

    'tässä on delay hidastamaan turhan nopeeta juoksua
    alkuaika = TIMER
    DO: LOOP UNTIL TIMER - alkuaika => .01

LOOP UNTIL foo$ = CHR$(27)
SCREEN 0, , 0, 0
WIDTH 80, 25
CLS
COLOR 15
PRINT "NYT TULI KOLLIISSIO :("
PRINT ""
PRINT "Ampuksia:"; shots
PRINT "Kaatoja:"; frags; "/"; asteroids
PRINT
PRINT
'lasketaan accuracy eli osumistarkkuusprossa:
IF shots = 0 THEN a = 0 ELSE a = INT(frags / shots * 1000) / 10
PRINT "  OSUMISTARKKAILU:"; a; "%"
COLOR 8: LOCATE 23, 53: PRINT "Puhveli teki 10.3.2005"
SLEEP
COLOR 7: CLOSE : END: STOP: SYSTEM

SUB killasteroid (i)
'tämä subi räjäyttää asteroidin kirjaimellisesti palasiksi
'i = asteroidin arrayindexi

    IF asteroid(i).lifetime = -1 THEN
        IF asteroid(i).radius > 11 THEN
            'jos asteroidi on iso, se halkeaa kahtia
            FOR CountDown = 1 TO 2
                a = RND * 360 * factor
                s = RND * 1.5
                newasteroid asteroid(i).x, asteroid(i).y, COS(a) * s, SIN(a) * s, asteroid(i).radius * .8, RND * 4 + 4, RND * 360, RND * 40 - 20, -1
            NEXT
        END IF
        'tehdään asteroidille sirpaleita (niiden lukumäärä riippuu asteroidin koosta)
        FOR CountDown = 1 TO asteroid(i).radius / 3 + 2
            a = RND * 360 * factor
            s = RND * 4 + 1
            newasteroid asteroid(i).x, asteroid(i).y, COS(a) * s, SIN(a) * s, RND * 4 + 2, RND * 3 + 3, RND * 360, RND * 40 - 20, RND * 30 + 5
        NEXT
    END IF
    asteroid(i).radius = 0
    frags = frags + 1

END SUB

SUB newasteroid (x, y, hor, ver, radius, nodes, angle, spin, lifetime)

    'etsitään ensimmäinen vapaa asteroidipaikka ja länttäistään asteroidin tiedot siihen
'(vihaan tätä vaihetta, siinä on liikaa monotonista kirjoittamista, mutta jonkun minun sen on tehtävä)
    FOR i = 1 TO UBOUND(asteroid)
        IF asteroid(i).radius = 0 THEN
            asteroid(i).x = x
            asteroid(i).y = y
            asteroid(i).hor = hor
            asteroid(i).ver = ver
            asteroid(i).radius = radius
            asteroid(i).nodes = nodes
            asteroid(i).angle = angle
            asteroid(i).spin = spin
            asteroid(i).lifetime = lifetime
            EXIT SUB
        END IF
    NEXT

END SUB

'Huhhuh se on siinä. Tulipas kommentoitua

ZcMander [16.03.2005 14:43:33]

#

Onhan nuitä nähty

sooda [19.03.2005 16:22:35]

#

Aika niinku vähän koodia noin hienolle pelille :)

Puhveli kirjoitti:

COLOR 7: CLOSE : END: STOP: SYSTEM

:D

Puhveli [19.03.2005 16:44:32]

#

Misiköhän tämä muuten edes on täällä..? Muistaakseni poistin tämän heti kun ajattelin että vinkiksi on aika turha :D
Rupesin virittelemään edelleen ja tässä on valmis: http://sooda.dy.fi:8080/mordor/dl/asteroid.exe

hunajavohveli [19.03.2005 16:58:52]

#

Ihan kiva. Muuttujia olisi kannattanut määritellä enemmän kokonaisluvuiksi, niin olisi nopeuttanut. Esim. kaikki taulukkoindeksit.

J.J. [19.04.2005 18:58:29]

#

Muuten hiano, mutta hyvä näppäimistö handleri ois paikallaan :)

moptim [21.07.2006 14:46:44]

#

ei toimi (valittaa eka et 8080 on liikaa ja sit sitä tiedostoo ei oo siel)

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta