Added pp1.
This commit is contained in:
parent
88c96b234c
commit
4fbe09e71f
|
@ -0,0 +1,85 @@
|
|||
#lang racket
|
||||
|
||||
(provide fill-abilities)
|
||||
(provide compose-abilities)
|
||||
(provide hourglass)
|
||||
|
||||
(provide (struct-out ability))
|
||||
(provide (struct-out abilities))
|
||||
|
||||
(provide get-ability-image)
|
||||
(provide get-ability-time)
|
||||
(provide get-ability-pos)
|
||||
(provide get-ability-next)
|
||||
|
||||
(require "random.rkt")
|
||||
(require lang/posn)
|
||||
(require 2htdp/image)
|
||||
|
||||
; Imaginea si range-ul în care vor aparea abilitațile
|
||||
; Nu modificați
|
||||
(define POSITION_RANGE '((300 2000) (30 550)))
|
||||
(define (hourglass color) (underlay
|
||||
(rectangle 40 40 "solid" color)
|
||||
(polygon
|
||||
(list (make-posn 0 0)
|
||||
(make-posn 25 0)
|
||||
(make-posn 0 25)
|
||||
(make-posn 25 25))
|
||||
"outline"
|
||||
(make-pen "darkslategray" 5 "solid" "round" "round"))))
|
||||
|
||||
; ABILITY
|
||||
; image: corresponding image for ability
|
||||
; time: how much the ability lasts
|
||||
; pos: position
|
||||
; next: function that receives variables from state and modifies them
|
||||
(struct ability (image time pos next) #:transparent)
|
||||
|
||||
; ABILITIES
|
||||
; visible abilities
|
||||
; active abilities
|
||||
(struct abilities (visible active) #:transparent)
|
||||
|
||||
; Fiecare funcție returneaza o componenta a unei abilități.
|
||||
(define (get-ability-image ability) (ability-image ability))
|
||||
(define (get-ability-time ability) (ability-time ability))
|
||||
(define (get-ability-pos ability) (ability-pos ability))
|
||||
(define (get-ability-next ability) (ability-next ability))
|
||||
|
||||
; Returneaza o poziție aleatorie în POSITION_RANGE.
|
||||
(define (random-position range)
|
||||
(apply make-posn (map ((curry apply) random) range)))
|
||||
|
||||
; Returnează o listă de n elemente alese aleatoriu din lista L.
|
||||
(define (choice-abilities n L)
|
||||
(sample (discrete-dist L) n))
|
||||
|
||||
; Va parcurge abitatile și pentru cele care au poziția null va asigna
|
||||
; una aletorie.
|
||||
; Folosiți random-position
|
||||
(define (position-abilities abilities)
|
||||
(map (lambda (curr-ability)
|
||||
(if (null? (get-ability-pos curr-ability))
|
||||
(struct-copy ability
|
||||
curr-ability
|
||||
[pos (random-position POSITION_RANGE)])
|
||||
curr-ability))
|
||||
abilities))
|
||||
|
||||
; Fiecare abilitate are o funcție next care modifica stare jocului
|
||||
; Compuneti toate funcțiile next în una singură
|
||||
; Hint: compose
|
||||
(define (compose-abilities L)
|
||||
(apply compose (foldr (lambda (L-ability acc) (cons (ability-next L-ability) acc)) '() L)))
|
||||
|
||||
; Primiște o listă de abilități inițiale, un număr n
|
||||
; și o listă cu toate abilități posibile.
|
||||
; Va adauga elemente aleatoare la lista inițială pană aceasta are lungimea n
|
||||
; Atentie n poate fi chiar si 0 cand vrem sa jucam fara nicio abilitate.
|
||||
; Folosiți choice-abilities.
|
||||
(define (fill-abilities initial n abilities)
|
||||
(cond [(zero? n) '()]
|
||||
[(<= n (length initial)) initial]
|
||||
[else (position-abilities (append initial
|
||||
(choice-abilities (- n (length initial)) abilities)))]))
|
|
@ -0,0 +1,45 @@
|
|||
; Constante pentru joc
|
||||
; Nu modificați imaginile de referință sunt create pentru aceste valori.
|
||||
#lang racket
|
||||
(require lang/posn)
|
||||
(provide (all-defined-out))
|
||||
|
||||
(define fps 28.0)
|
||||
|
||||
(define scene-height 960)
|
||||
(define scene-width 640)
|
||||
|
||||
(define ground-height (quotient scene-height 6))
|
||||
(define ground-y (- scene-height ground-height))
|
||||
|
||||
(define initial-gravity 1.3)
|
||||
(define initial-momentum 15.0)
|
||||
|
||||
(define bird-width 81)
|
||||
(define bird-height 57)
|
||||
(define bird-x (quotient scene-width 3))
|
||||
(define bird-initial-y (quotient scene-height 2))
|
||||
|
||||
(define pipe-width 104)
|
||||
(define pipe-height scene-height)
|
||||
(define pipe-gap 232.75)
|
||||
(define pipe-self-gap 280)
|
||||
|
||||
(define initial-scroll-speed 7.0)
|
||||
|
||||
(define added-number (quotient scene-height 8))
|
||||
(define random-threshold (- (- scene-height (* 2 added-number)) pipe-self-gap))
|
||||
|
||||
(define no-pipes 6)
|
||||
(define text-height 50)
|
||||
(define text-x (- scene-width 50))
|
||||
(define text-y 50)
|
||||
(define text-posn (make-posn (- scene-width 50) 50))
|
||||
(define abilities-posn (make-posn (- scene-width 50) 80))
|
||||
(define DISPLAYED_ABILITIES 4)
|
||||
(define SHOW_SCORE #t)
|
||||
|
||||
; checker stuff
|
||||
(define (disable-score) (set! SHOW_SCORE #f))
|
||||
(define (disable-bonus) (set! DISPLAYED_ABILITIES 0))
|
||||
(define (enable-bonus) (set! DISPLAYED_ABILITIES 4))
|
|
@ -0,0 +1,561 @@
|
|||
#lang racket/gui
|
||||
;Ignorați următoarele linii de cod. Conțin import-uri și export-uri necesare checker-ului.
|
||||
|
||||
(require 2htdp/image)
|
||||
(require 2htdp/universe)
|
||||
(require lang/posn)
|
||||
|
||||
(require "random.rkt")
|
||||
(require "abilities.rkt")
|
||||
(require "constants.rkt")
|
||||
;---------------------------------------checker_exports------------------------------------------------
|
||||
(provide next-state)
|
||||
(provide next-state-bird)
|
||||
(provide next-state-bird-onspace)
|
||||
(provide change)
|
||||
|
||||
(provide get-pipes)
|
||||
(provide get-pipe-x)
|
||||
(provide next-state-pipes)
|
||||
(provide add-more-pipes)
|
||||
(provide clean-pipes)
|
||||
(provide move-pipes)
|
||||
|
||||
(provide invalid-state?)
|
||||
(provide check-ground-collision)
|
||||
(provide check-pipe-collisions)
|
||||
|
||||
(provide draw-frame)
|
||||
|
||||
(provide get-initial-state)
|
||||
(provide get-bird)
|
||||
(provide get-bird-y)
|
||||
(provide get-bird-v-y)
|
||||
|
||||
; pipe
|
||||
(provide get-pipes)
|
||||
(provide get-pipe-x)
|
||||
|
||||
; score25
|
||||
(provide get-score)
|
||||
|
||||
(provide get-abilities)
|
||||
(provide get-abilities-visible)
|
||||
(provide get-abilities-active)
|
||||
; variables
|
||||
(provide get-variables)
|
||||
(provide get-variables-gravity)
|
||||
(provide get-variables-momentum)
|
||||
(provide get-variables-scroll-speed)
|
||||
|
||||
|
||||
;---------------------------------------checker_exports------------------------------------------------
|
||||
; Checker-ul contine un numar de teste, fiecare cu numele sau. In acest fisier veti gasi comentarii
|
||||
; care incep cu TODO %nume_test, unde trebuie sa modificati sau sa implementati o functie, pentru
|
||||
; a trece testul %nume_test.
|
||||
;
|
||||
;Initial state
|
||||
; Primul pas pe care trebuie sa il facem este sa cream starea initiala a jocului.
|
||||
; Aceasta va fi salvata in (get-initial-state), si trebuie sa incapsuleze toate informatiile
|
||||
; necesare jocului, si anume: informatii despre pasare, despre pipes si despre powerups.
|
||||
; Recomandam ca in pasare, sa retineti, printre altele, informatii despre y-ul curent
|
||||
; si viteza pe y
|
||||
; Pe parcursul temei, in state, salvati coordonatele colturilor din stanga sus ale obiectelor.
|
||||
; Aceasta va face mai usoara atat logica miscarii obiectelor, cat si testarea cerintelor.
|
||||
; Toate coordonatele oferite in comentarii sau in fisierul constants.rkt, se refera la
|
||||
; coltul din stanga sus ale obiectelor!
|
||||
;Inițial state
|
||||
; Primul pas pe care trebuie să îl facem este să creăm starea inițială a jocului.
|
||||
; Aceasta va fi salvată în (get-initial-state), și trebuie să incapsuleze toate informațiile
|
||||
; necesare jocului, și anume: informații despre pasăre, despre pipes și, pentru bonus,
|
||||
; despre powerups și despre variabilele de mediu.
|
||||
; Recomandăm ca în pasăre, să rețineți, printre altele, informații despre y-ul curent
|
||||
; și viteză pe y.
|
||||
; Pe parcursul temei, în state, salvați coordonatele colțurilor din stânga sus ale obiectelor.
|
||||
; Aceasta va face mai ușoară atât logică mișcării obiectelor, cât și testarea cerințelor.
|
||||
; Toate coordonatele oferite în comentarii sau în fișierul variables.rkt se referă la
|
||||
; colțul din stânga sus ale obiectelor!
|
||||
|
||||
;TODO 1
|
||||
; După ce definiți structurile lui (get-initial-state) și a păsării, introduceți în prima
|
||||
; pe cea din urmă. Colțul din stânga sus a păsării se va află inițial la:
|
||||
; y = bird-inițial-y
|
||||
; și x = bird-x.
|
||||
; (get-initial-state) va fi o funcție care va returna starea inițială a jocului.
|
||||
|
||||
; BIRD:
|
||||
; v: pozitia pe verticala
|
||||
; v-y: viteza pe verticala
|
||||
(struct bird (y v-y) #:transparent)
|
||||
|
||||
; PIPE:
|
||||
; gap-y: pozitia gap-ului pe verticala
|
||||
; x: pozitia pe orizontala
|
||||
(struct pipe (gap-y x) #:transparent)
|
||||
|
||||
; VARIABLES:
|
||||
; gravity
|
||||
; momentum
|
||||
; scroll-speed
|
||||
(struct variables (gravity momentum scroll-speed) #:transparent)
|
||||
|
||||
; STATE:
|
||||
; bird
|
||||
; pipes
|
||||
; variables
|
||||
; score
|
||||
(struct state (bird pipes variables score abilities) #:transparent)
|
||||
|
||||
; Getters for variables
|
||||
(define (get-variables state) (state-variables state))
|
||||
|
||||
(define (get-variables-gravity variables)
|
||||
(variables-gravity variables))
|
||||
(define (get-variables-momentum variables)
|
||||
(variables-momentum variables))
|
||||
(define (get-variables-scroll-speed variables)
|
||||
(variables-scroll-speed variables))
|
||||
|
||||
;TODO 8
|
||||
; În starea jocului, trebuie să păstrăm informații despre pipes. Pe parcursul jocului,
|
||||
; pipe-urile se vor schimba, unele vor fi șterse și vor fi adăugate altele.
|
||||
; După ce definiți structura pentru pipe și pentru mulțimea de pipes din stare,
|
||||
; adăugați primul pipe în starea jocului. Acesta se va află inițial în afară ecranului.
|
||||
; Celelalte pipe-uri vor fi adăugate ulterior, poziționându-le după acest prim pipe.
|
||||
; Atenție! Fiecare pipe este format din 2 părți, cea superioară și cea inferioară,
|
||||
; acestea fiind despărțite de un gap de înălțime pipe-self-gap.
|
||||
; Colțul din stânga sus al gap-ului dintre componentele primului pipe se va afla inițial la:
|
||||
; y = (+ added-number (random random-threshold)), pentru a da un element de noroc jocului,
|
||||
; și x = scene-width,
|
||||
; pentru a-l forța să nu fie inițial pe ecran.
|
||||
; Atenție! Recomandăm să păstrați în stare colțul din stânga sus al chenarului lipsa
|
||||
; dintre cele 2 pipe-uri!
|
||||
(define (get-initial-pipes)
|
||||
(list (pipe (+ added-number (random random-threshold))
|
||||
scene-width)))
|
||||
|
||||
;TODO 16
|
||||
; Vrem o modalitate de a păstra scorul jocului. După ce definiți structura
|
||||
; acestuia, adăugați scorul inițial, adică 0, în starea inițială a jocului.
|
||||
; Atenție get-initial-state trebuie sa fie o funcție
|
||||
; și trebuie apelată în restul codului.
|
||||
(define (get-initial-state)
|
||||
(state (bird bird-initial-y 0)
|
||||
(get-initial-pipes)
|
||||
(variables initial-gravity
|
||||
initial-momentum
|
||||
initial-scroll-speed)
|
||||
0
|
||||
(delay (abilities (fill-abilities '()
|
||||
DISPLAYED_ABILITIES
|
||||
ABILITIES)
|
||||
'()))))
|
||||
|
||||
;TODO 2
|
||||
; După aceasta, implementați un getter care extrage din structura voastră
|
||||
; pasărea, și un al doilea getter care extrage din structura pasăre
|
||||
; y-ul curent pe care se află această.
|
||||
(define (get-bird state)
|
||||
(state-bird state))
|
||||
(define (get-bird-y bird)
|
||||
(bird-y bird))
|
||||
|
||||
;TODO 4
|
||||
; După aceasta, implementati un getter care extrage din structura voastră
|
||||
; viteza pe y a păsării.
|
||||
(define (get-bird-v-y bird)
|
||||
(bird-v-y bird))
|
||||
|
||||
;TODO 3
|
||||
; Trebuie să implementăm logică gravitației. next-state-bird va primi drept
|
||||
; parametri o structură de tip pasăre, și gravitația(un număr real). Aceasta va adaugă
|
||||
; pozitiei pe y a păsării viteza acesteia pe y, si va adaugă vitezei pe y a păsării,
|
||||
; gravitația.
|
||||
(define (next-state-bird curr-bird gravity)
|
||||
(let ([curr-y (get-bird-y curr-bird)] [curr-v-y (get-bird-v-y curr-bird)])
|
||||
(bird (+ curr-y curr-v-y) (+ curr-v-y gravity))))
|
||||
|
||||
;TODO 6
|
||||
; Dorim să existe un mod prin care să imprimăm păsării un impuls.
|
||||
; Definiți funcția next-state-bird-onspace care va primi drept parametri
|
||||
; o structură de tip pasăre, momentum(un număr real), și va schimba viteza
|
||||
; pe y a păsării cu -momentum.
|
||||
(define (next-state-bird-onspace curr-bird momentum)
|
||||
(let ([curr-v-y (get-bird-v-y curr-bird)])
|
||||
(bird (get-bird-y curr-bird) (- momentum))))
|
||||
|
||||
; Change
|
||||
; Change va fi responsabil de input-ul de la tastatură al jocului.
|
||||
;TODO 7
|
||||
; Acesta va primi drept parametri o structură de tip stare, și tasta pe
|
||||
; care am apăsat-o. Aceasta va imprimă păsării momentum-ul, apelând
|
||||
; funcția next-state-bird-onspace. Pentru orice altă tasta, starea rămâne aceeași.
|
||||
(define (change curr-state pressed-key)
|
||||
(let ([curr-bird (get-bird curr-state)]
|
||||
[curr-mom (get-variables-momentum (get-variables curr-state))])
|
||||
(cond [(key=? pressed-key " ")
|
||||
(struct-copy state
|
||||
curr-state
|
||||
[bird (next-state-bird-onspace curr-bird curr-mom)])]
|
||||
[else curr-state])))
|
||||
|
||||
;TODO 9
|
||||
; După ce ați definit structurile pentru mulțimea de pipes și pentru un singur pipe,
|
||||
; implementați getterul get-pipes, care va extrage din starea jocului mulțimea de pipes,
|
||||
; sub formă de lista.
|
||||
(define (get-pipes state)
|
||||
(state-pipes state))
|
||||
|
||||
;TODO 10
|
||||
; Implementați get-pipe-x ce va extrage dintr-o singură structura de tip pipe, x-ul acesteia.
|
||||
(define(get-pipe-x pipe)
|
||||
(pipe-x pipe))
|
||||
|
||||
(define (get-pipe-gap-y pipe)
|
||||
(pipe-gap-y pipe))
|
||||
|
||||
;TODO 11
|
||||
; Trebuie să implementăm logica prin care se mișcă pipes.
|
||||
; Funcția move-pipes va primi drept parametri mulțimea pipe-urilor din stare
|
||||
; și scroll-speed(un număr real). Aceasta va scădea din x-ul fiecărui pipe
|
||||
; scroll-speed-ul dat.
|
||||
(define (move-pipes pipes scroll-speed)
|
||||
(map (lambda (curr-pipe)
|
||||
(let ([curr-x (get-pipe-x curr-pipe)])
|
||||
(struct-copy pipe
|
||||
curr-pipe
|
||||
[x (- curr-x scroll-speed)])))
|
||||
pipes))
|
||||
|
||||
;TODO 12
|
||||
; Vom implementa logica prin care pipe-urile vor fi șterse din stare. În momentul
|
||||
; în care colțul din DREAPTA sus al unui pipe nu se mai află pe ecran, acesta trebuie
|
||||
; șters.
|
||||
; Funcția va primi drept parametru mulțimea pipe-urilor din stare.
|
||||
;
|
||||
; Hint: cunoaștem lățimea unui pipe, pipe-width
|
||||
(define (clean-pipes pipes)
|
||||
(filter (lambda (curr-pipe)
|
||||
(>= (+ (get-pipe-x curr-pipe) pipe-width) 0))
|
||||
pipes))
|
||||
|
||||
|
||||
;TODO 13
|
||||
; Vrem să avem un sursa continuă de pipe-uri.
|
||||
; Implementati funcția add-more-pipes, care va primi drept parametru mulțimea pipe-urilor
|
||||
; din stare și, dacă avem mai puțin de no-pipes pipe-uri, mai adăugăm una la mulțime,
|
||||
; având x-ul egal cu pipe-width + pipe-gap + x-ul celui mai îndepărtat pipe, în raport
|
||||
; cu pasărea.
|
||||
(define (add-more-pipes pipes)
|
||||
(if (equal? (length pipes) no-pipes)
|
||||
pipes
|
||||
(letrec ([last-pipe (car (reverse pipes))] [last-pipe-x (get-pipe-x last-pipe)])
|
||||
(append pipes
|
||||
(list (pipe (+ added-number (random random-threshold))
|
||||
(+ last-pipe-x pipe-gap pipe-width)))))))
|
||||
|
||||
;TODO 14
|
||||
; Vrem ca toate funcțiile implementate anterior legate de pipes să fie apelate
|
||||
; de către next-state-pipes.
|
||||
; Aceasta va primi drept parametri mulțimea pipe-urilor și scroll-speed-ul,
|
||||
; și va apela cele trei funcții implementate anterior, în această ordine:
|
||||
; move-pipes, urmat de clean-pipes, urmat de add-more pipes.
|
||||
(define (next-state-pipes pipes scroll-speed)
|
||||
(letrec ([moved-pipes (move-pipes pipes scroll-speed)]
|
||||
[cleaned-pipes (clean-pipes moved-pipes)]
|
||||
[added-pipes (add-more-pipes cleaned-pipes)])
|
||||
added-pipes))
|
||||
|
||||
;TODO 17
|
||||
; Creați un getter ce va extrage scorul din starea jocului.
|
||||
(define (get-score state)
|
||||
(state-score state))
|
||||
|
||||
;TODO 19
|
||||
; Vrem să creăm logica coliziunii cu pământul.
|
||||
; Implementati check-ground-collision, care va primi drept parametru
|
||||
; o structura de tip pasăre, și returnează true dacă aceasta are coliziune
|
||||
; cu pământul.
|
||||
;
|
||||
; Hint: știm înălțimea păsării, bird-height, și y-ul pământului, ground-y.
|
||||
; Coliziunea ar presupune ca un colț inferior al păsării să aibă y-ul
|
||||
; mai mare sau egal cu cel al pământului.
|
||||
(define (check-ground-collision bird)
|
||||
(let ([bird-bottom-corner (+ (get-bird-y bird) bird-height)])
|
||||
(>= bird-bottom-corner ground-y)))
|
||||
|
||||
; invalid-state?
|
||||
; invalid-state? îi va spune lui big-bang dacă starea curentă mai este valida,
|
||||
; sau nu. Aceasta va fi validă atât timp cât nu avem coliziuni cu pământul
|
||||
; sau cu pipes.
|
||||
; Aceasta va primi ca parametru starea jocului.
|
||||
|
||||
;TODO 20
|
||||
; Vrem să integrăm verificarea coliziunii cu pământul în invalid-state?.
|
||||
|
||||
;TODO 22
|
||||
; Odată creată logică coliziunilor dintre pasăre și pipes, vrem să integrăm
|
||||
; funcția nou implementată în invalid-state?.
|
||||
(define (invalid-state? state)
|
||||
(let ([bird (get-bird state)] [pipes (get-pipes state)])
|
||||
(or (check-ground-collision bird) (check-pipe-collisions bird pipes))))
|
||||
|
||||
;TODO 21
|
||||
; Odată ce am creat pasărea, pipe-urile, scor-ul și coliziunea cu pământul,
|
||||
; următorul pas este verificarea coliziunii dintre pasăre și pipes.
|
||||
; Implementati funcția check-pipe-collisions care va primi drept parametri
|
||||
; o structură de tip pasăre, mulțimea de pipes din stare, și va returna
|
||||
; true dacă există coliziuni, și false în caz contrar. Reiterând,
|
||||
; fiecare pipe este format din 2 părți, cea superioară și cea inferioară,
|
||||
; acestea fiind despărțite de un gap de înălțime pipe-self-gap. Pot există
|
||||
; coliziuni doar între pasăre și cele două părți. Dacă pasărea se află în
|
||||
; chenarul lipsă, nu există coliziune.
|
||||
;
|
||||
; Hint: Vă puteți folosi de check-collision-rectangle, care va primi drept parametri
|
||||
; colțul din stânga sus și cel din dreapta jos ale celor două dreptunghiuri
|
||||
; pe care vrem să verificăm coliziunea.
|
||||
(define (check-pipe-collisions bird pipes)
|
||||
; A1 - upper left corner of bird
|
||||
; A2 - bottom right corner of bird
|
||||
|
||||
; B1 - upper left corner of upper pipe
|
||||
; B2 - bottom right corner of upper pipe
|
||||
|
||||
; C1 - upper left corner of bottom pipe
|
||||
; C2 - bottom right corner of bottom pipe
|
||||
|
||||
(ormap (lambda (pipe)
|
||||
(let ([A1 (make-posn bird-x (get-bird-y bird))]
|
||||
[A2 (make-posn (+ bird-x bird-width) (+ (get-bird-y bird) bird-height))]
|
||||
[B1 (make-posn (get-pipe-x pipe) 0)]
|
||||
[B2 (make-posn (+ (get-pipe-x pipe) pipe-width) (get-pipe-gap-y pipe))]
|
||||
[C1 (make-posn (get-pipe-x pipe) (+ (get-pipe-gap-y pipe) pipe-self-gap))]
|
||||
[C2 (make-posn (+ (get-pipe-x pipe) pipe-width) scene-height)])
|
||||
(or (check-collision-rectangles A1 A2 B1 B2)
|
||||
(check-collision-rectangles A1 A2 C1 C2))))
|
||||
pipes))
|
||||
|
||||
(define (check-collision-rectangles A1 A2 B1 B2)
|
||||
(match-let ([(posn AX1 AY1) A1]
|
||||
[(posn AX2 AY2) A2]
|
||||
[(posn BX1 BY1) B1]
|
||||
[(posn BX2 BY2) B2])
|
||||
(and (< AX1 BX2) (> AX2 BX1) (< AY1 BY2) (> AY2 BY1))))
|
||||
|
||||
;Next-state
|
||||
; Next-state va fi apelat de big-bang la fiecare cadru, pentru a crea efectul de
|
||||
; animație. Acesta va primi ca parametru o structură de tip stare, și va întoarce
|
||||
; starea corespunzătoare următorului cadru.
|
||||
|
||||
;TODO 5
|
||||
; Trebuie să integrăm funcția implementată anterior, și anume next-state-bird,
|
||||
; în next-state.
|
||||
|
||||
;TODO 15
|
||||
; Vrem să implementăm logică legată de mișcarea, ștergerea și adăugarea pipe-urilor
|
||||
; în next-state. Acesta va apela next-state-pipes pe pipe-urile din starea curentă.
|
||||
|
||||
;TODO 18
|
||||
; Vrem ca next-state să incrementeze scorul cu 0.1 la fiecare cadru.
|
||||
(define (next-state curr-state)
|
||||
(letrec ([curr-bird (get-bird curr-state)]
|
||||
[curr-pipes (get-pipes curr-state)]
|
||||
[curr-vars (get-variables curr-state)]
|
||||
[curr-gravity (get-variables-gravity curr-vars)]
|
||||
[curr-scroll-speed (get-variables-scroll-speed curr-vars)]
|
||||
[curr-score (get-score curr-state)])
|
||||
(struct-copy state
|
||||
curr-state
|
||||
[bird (next-state-bird curr-bird curr-gravity)]
|
||||
[pipes (next-state-pipes curr-pipes curr-scroll-speed)]
|
||||
[score (+ curr-score 0.1)])))
|
||||
|
||||
; draw-frame
|
||||
; draw-frame va fi apelat de big-bang dupa fiecare apel la next-state, pentru a afisa cadrul curent.
|
||||
;TODO 23
|
||||
; Fiecare cadru va fi desenat in urmatorul mod:
|
||||
; bird peste ground, peste scor, peste pipes, peste empty-scene.
|
||||
;
|
||||
; Hint: score-to-image primeste un numar real si intoarce scor-ul sub forma de imagine;
|
||||
; Scor-ul îl puteți plasa direct la coordonatele date, fără a mai face translatiile menționate mai jos.
|
||||
; Noi tinem minte coltul din stanga sus al imaginii, insa, la suprapunerea unei imagini A peste o alta imagine,
|
||||
; coordonatele unde plasam imaginea A reprezinta centrul acesteia. Trebuie facute translatiile de la coltul din stanga
|
||||
; sus la centrul imaginilor.
|
||||
; Variabile folosite in aceasta functie:
|
||||
; bird -> bird-width si bird-height
|
||||
; ground -> ground-y si ground-height, acesta va acoperi intreaga latime a ecranului
|
||||
; scor -> text-x si text-y
|
||||
; pipes -> pipe-width si pipe-height
|
||||
(define bird-image (rectangle bird-width bird-height "solid" "yellow"))
|
||||
(define ground-image (rectangle scene-width ground-height "solid" "brown"))
|
||||
(define initial-scene (rectangle scene-width scene-height "solid" "white"))
|
||||
(define (get-pipe-img pipe-height) (rectangle pipe-width pipe-height "solid" "green"))
|
||||
|
||||
(define text-family (list "Gill Sans" 'swiss 'normal 'bold #f))
|
||||
(define (score-to-image x)
|
||||
(if SHOW_SCORE
|
||||
(apply text/font (~v (round x)) 24 "indigo" text-family)
|
||||
empty-image))
|
||||
|
||||
(define (place-ground scene)
|
||||
(place-image ground-image (quotient scene-width 2) (+ ground-y (quotient ground-height 2)) scene))
|
||||
|
||||
(define (place-score score scene)
|
||||
(place-image (score-to-image score) text-x text-y scene))
|
||||
|
||||
(define (place-bird bird-y scene)
|
||||
(place-image bird-image (+ bird-x (quotient bird-width 2)) (+ bird-y (quotient bird-height 2)) scene))
|
||||
|
||||
(define (draw-frame state)
|
||||
(let ([bird-y (get-bird-y (get-bird state))]
|
||||
[score (get-score state)]
|
||||
[pipes (get-pipes state)])
|
||||
(place-bird bird-y (place-score score (place-ground (place-pipes pipes initial-scene))))))
|
||||
|
||||
; Folosind `place-image/place-images` va poziționa pipe-urile pe scenă.
|
||||
(define (place-pipes pipes scene)
|
||||
(if (empty? pipes)
|
||||
scene
|
||||
(letrec ([upper-pipe-x (+ (get-pipe-x (car pipes))
|
||||
(quotient pipe-width 2))]
|
||||
[upper-pipe-y (quotient (get-pipe-gap-y (car pipes)) 2)]
|
||||
[lower-pipe-x upper-pipe-x]
|
||||
[lower-pipe-y (quotient (+ scene-height (get-pipe-gap-y (car pipes)) pipe-self-gap) 2)])
|
||||
|
||||
(place-pipes (cdr pipes)
|
||||
(place-image (get-pipe-img (- scene-height (get-pipe-gap-y (car pipes)) pipe-self-gap))
|
||||
lower-pipe-x
|
||||
lower-pipe-y
|
||||
(place-image (get-pipe-img (get-pipe-gap-y (car pipes)))
|
||||
upper-pipe-x
|
||||
upper-pipe-y
|
||||
scene))))))
|
||||
|
||||
; Bonus
|
||||
; Completați abilities.rkt mai întâi, aceste funcții căt, apoi legați
|
||||
; această funcționalitate la jocul inițial.
|
||||
|
||||
|
||||
; Abilitatea care va încetini timpul va dura 10 de secunde, va avea imaginea (hourglass "mediumseagreen")
|
||||
; va avea inițial poziția null si va modifica scrolls-speed dupa formulă
|
||||
; scroll-speed = max(5, scroll-speed - 1)
|
||||
(define slow-ability (ability (hourglass "mediumseagreen")
|
||||
10
|
||||
null
|
||||
(lambda (scroll-speed)
|
||||
(max 5 (sub1 scroll-speed)))))
|
||||
|
||||
; Abilitatea care va accelera timpul va dura 30 de secunde, va avea imaginea (hourglass "tomato")
|
||||
; va avea inițial poziția null si va modifica scrolls-speed dupa formulă
|
||||
; scroll-speed = scroll-speed + 1
|
||||
(define fast-ability (ability (hourglass "tomato")
|
||||
30
|
||||
null
|
||||
add1))
|
||||
|
||||
; lista cu toate abilităţile posibile în joc
|
||||
(define ABILITIES (list fast-ability slow-ability))
|
||||
|
||||
; Întoarce abilităţile din stare, cu o reprezentare
|
||||
; intermediară care trebuie să conțină două liste:
|
||||
; - lista abilităţilor vizibile (încarcate în scenă dar nu neaparat vizibile pe ecran).
|
||||
; - lista abilităţilor activate (cu care pasărea a avut o coloziune).
|
||||
(define (get-abilities x) (force (state-abilities x)))
|
||||
|
||||
; Întoarce abilităţile vizibile din reprezentarea intermediară.
|
||||
(define (get-abilities-visible x) (abilities-visible x))
|
||||
|
||||
; Întoarce abilităţile active din reprezentarea intermediară.
|
||||
(define (get-abilities-active x) (abilities-active x))
|
||||
|
||||
; Șterge din reprezentarea abilităţilor vizibile pe cele care nu mai sunt vizibile.
|
||||
; echivalent cu clean-pipes.
|
||||
(define (clean-abilities abilities)
|
||||
'your-code-here)
|
||||
; (let ([visible (get-abilities-visible abilities)])
|
||||
; (filter (lambda (curr-ability)
|
||||
; (>= (+ (posn-x (get-ability-pos curr-ability)) 20) 0))
|
||||
; visible)))
|
||||
|
||||
|
||||
; Muta abilităţile vizibile spre stanga.
|
||||
; echivalent cu move-pipes.
|
||||
(define (move-abilities abilities scroll-speed)
|
||||
'your-code-here)
|
||||
; (let ([visible (get-abilities-visible abilities)])
|
||||
; (map (lambda (curr-ability)
|
||||
; (let ([curr-x (posn-x (get-ability-pos curr-ability))]
|
||||
; [curr-y (posn-y (get-ability-pos curr-ability))])
|
||||
; (struct-copy ability
|
||||
; curr-ability
|
||||
; [pos (make-posn (- curr-x scroll-speed) curr-y)])))
|
||||
; visible)))
|
||||
|
||||
|
||||
; Scurge timpul pentru abilităţile activate și le sterge pe cele care au expirat.
|
||||
; Puteți să va folosiți de variabila globală fps.
|
||||
(define (time-counter abilities)
|
||||
'your-code-here)
|
||||
; (let ([active (get-abilities-active abilities)])
|
||||
; (filter (lambda (curr-ability)
|
||||
; (positive? (get-ability-time curr-ability)))
|
||||
; (map (lambda (curr-ability)
|
||||
; (let ([curr-time (get-ability-time curr-ability)])
|
||||
; (struct-copy ability
|
||||
; curr-ability
|
||||
; [time (- curr-time (/ 1 fps))])))
|
||||
; active))))
|
||||
|
||||
; Generează următoarele abilitați vizibile.
|
||||
; *Atentie* La orice moment pe scena trebuie să fie exact DISPLAYED_ABILITIES
|
||||
; abilităţi vizibile
|
||||
; Folosiți funcția fill-abilities din abilities.rkt cât si cele scrise mai sus:
|
||||
; move-abilities, clean-abilities, time-counter, etc..
|
||||
(define (next-abilities-visible visible scroll-speed)
|
||||
'your-code-here)
|
||||
; (letrec ([moved-abilities (move-abilities visible scroll-speed)]
|
||||
; [cleaned-abilities (clean-abilities moved-abilities)]
|
||||
; [filled-abilities (fill-abilities cleaned-abilities
|
||||
; (- DISPLAYED_ABILITIES (length cleaned-abilities))
|
||||
; ABILITIES)])
|
||||
; filled-abilities))
|
||||
|
||||
|
||||
; Generează structura intermediară cu abilități.
|
||||
; Observați ca nu există next-abilities-active aceastea sunt acele abilităti
|
||||
; întoarse next-abilities-visible care au o coliziune cu pasărea.
|
||||
; Puteti folosi `filer`/`filter-not` ca sa verificați ce abilităti au și abilitați
|
||||
; nu au coliziuni cu pasărea sau puteti folosi `partition`
|
||||
(define (next-abilities abilities bird scroll-speed)
|
||||
'your-code-here)
|
||||
|
||||
; Dând-use variabilele actuale și abilitațile calculați care vor
|
||||
; variabile finale folosite în joc
|
||||
; Folositi compose-abilities
|
||||
; Atenție când apelați `next-variables` în next-state dați ca paremetru
|
||||
; initial-variables și nu variabilele aflate deja în stare
|
||||
; In felul acesta atunci când
|
||||
(define (next-variables variables abilities)
|
||||
'your-code-here)
|
||||
|
||||
|
||||
; Folosind `place-image/place-images` va poziționa abilităţile vizibile la ability pos.
|
||||
(define (place-visible-abilities abilities scene)
|
||||
'your-code-here)
|
||||
|
||||
; Folosind `place-image/place-images` va poziționa abilităţile active
|
||||
; în partea de sus a ecranului lângă scor.
|
||||
; Imaginiile vor scalate cu un factor de 0.75 și așezate plecând
|
||||
; de la ability-posn (constantă globală) cu spații de 50 de px.
|
||||
; Imaginea cu indexul i va fi așezată la (ability-posn.x - 50*i, ability-posn.y)
|
||||
(define (place-active-abilities abilities scene)
|
||||
'your-code-here)
|
||||
|
||||
(module+ main
|
||||
(big-bang (get-initial-state)
|
||||
[on-tick next-state (/ 1.0 fps)]
|
||||
[to-draw draw-frame]
|
||||
[on-key change]
|
||||
[stop-when invalid-state?]
|
||||
[close-on-stop #t]
|
||||
[record? #f]))
|
|
@ -0,0 +1,33 @@
|
|||
#lang racket
|
||||
(require math)
|
||||
(provide make-predictive)
|
||||
(provide remove-predictive)
|
||||
(provide discrete-dist)
|
||||
(provide (rename-out [_random random]))
|
||||
(provide (rename-out [_sample sample]))
|
||||
|
||||
(define r random)
|
||||
(define s sample)
|
||||
(define seq '(32))
|
||||
(define (_random . x) (apply r x))
|
||||
(define (_sample . x) (apply s x))
|
||||
(define (fake-random . x)
|
||||
(when (> (length seq) 1) (set! seq (cdr seq)))
|
||||
(car seq))
|
||||
|
||||
(define (fake-sample . x)
|
||||
(match-let* ([(list d n) x]
|
||||
[L (discrete-dist-values d)])
|
||||
(cond [(> (- n (length L)) 0)
|
||||
(append L (make-list (- n (length L)) (car L)))]
|
||||
[(equal? n 0) '()]
|
||||
[else L])))
|
||||
|
||||
(define (make-predictive x)
|
||||
(set! seq (cons 0 x))
|
||||
(set! r fake-random)
|
||||
(set! s fake-sample))
|
||||
|
||||
(define (remove-predictive)
|
||||
(set! r sample)
|
||||
(set! s random))
|
|
@ -0,0 +1,57 @@
|
|||
I. Structuri folosite
|
||||
---------------------
|
||||
Structura principala folosita pentru aceasta tema este state, care inglobeaza
|
||||
alte structuri cum ar fi bird, pipe, variables si abilities. Valoarea initiala
|
||||
a acestei structuri se poate obtine prin apelul functiei get-initial-state,
|
||||
care contine toate datele necesare de la momentul 0 al jocului.
|
||||
|
||||
II. Logica jocului
|
||||
------------------
|
||||
Pentru a eficientiza timpul si efortul de lucru am impartit scheletul de cod
|
||||
in mai multe parti care se ocupa cu lucruri diferite ce vor fi puse cap la
|
||||
cap in final.
|
||||
|
||||
1. BIRD
|
||||
In prima parte a TODO-urilor, fisierul main se ocupa cu definirea getterilor
|
||||
si logicii miscarii bird-ului, ca in final sa rezulte functia next-state-bird
|
||||
care poate asigura functionarea bird-ului pe parcursul jocului.
|
||||
|
||||
2. PIPES
|
||||
Logica pentru pipes se asemana cu cea de la bird, elementul nou fiind ca se
|
||||
definesc functiile de move-pipes, clean-pipes si add-more-pipes care se
|
||||
integreaza in next-state-pipes. Aici am folosit foarte mult functionale precum
|
||||
map sau filter si functia struct-copy pentru a obtine structuri noi.
|
||||
|
||||
3. SCORE
|
||||
Pentru aceasta parte a fost nevoie doar de un getter si integrarea variabilei
|
||||
score in state.
|
||||
|
||||
4.COLLISIONS
|
||||
Pentru verificarea coliziunilor am integrat functiile check-ground-collision
|
||||
si check-pipe-collision in invalid-state?. Implementarea a fost relativ usoara,
|
||||
deoarece in schelet a fost data functia check-collision-rectangles care ajuta
|
||||
la detectarea coliziunilor dintre dreptunghiuri.
|
||||
|
||||
5. DRAWING
|
||||
Pentru punerea pe ecran a imaginilor am definit mai multe functii cum ar fi
|
||||
place-ground sau place-bird care apelate in draw-frame au facut posibila
|
||||
afisarea bird-ului, pipe-urilor, etc. Dificultatea aici a fost functia
|
||||
place-pipes deoarece am incercat o abordare cu place-images care insa n-a mers.
|
||||
Asa ca am luat fiecare pipe in parte, am calculat coordonatele si le-am pus
|
||||
peste scena goala.
|
||||
|
||||
6. ABILITIES
|
||||
Pentru abilities am folosit functiile delay si force pentru a intarzia
|
||||
calcularea lor pana in momentul cand era nevoie, deoarece altfel checkerul
|
||||
nu-mi dadea punctajul pentru subpunctele respective. Aici nu am reusit sa
|
||||
implementez afisarea pe ecran a abilitatilor, ci doar logica obtinerii
|
||||
abilitatilor vizibile.
|
||||
|
||||
|
||||
III. Concluzii si rezultate
|
||||
---------------------------
|
||||
Cand am incercat sa testez pe checker am observat ca pentru ultimul test de
|
||||
la bonus, checkerul da o eroare pe care n-am putut sa o rezolv. El valideaza
|
||||
toate testele pana la logica punerii abilitatilor pe ecran. Per total a fost
|
||||
o tema foarte folositoare deoarece mi-a intarit cunostintele despre functionale,
|
||||
intarzieri, structuri, etc in racket.
|
Loading…
Reference in New Issue