加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
world.rkt 4.56 KB
一键复制 编辑 原始数据 按行查看 历史
kuan291 提交于 2014-12-10 23:49 . add update-npcs
#lang racket
; world.rkt
(require
noise
thing)
(define world%
(class object%
; Store the player
(define player
(make-thing entity
[name "player"]
[attack 10]
[defense 10]
[health 100]))
(define/public (get-player)
player)
; Get the contents of a given point, caching for future use
; Hash on (x y) => char
(define tiles (make-hash))
(define/public (get-tile x y)
; If the tile doesn't already exist, generate it
(unless (hash-has-key? tiles (list x y))
; Generate a random tile
(define new-tile
(let ()
(define wall? (> (simplex (* 0.1 x) (* 0.1 y) 0) 0.0))
(define water? (> (simplex (* 0.1 x) 0 (* 0.1 y)) 0.5))
(define tree? (> (simplex 0 (* 0.1 x) (* 0.1 y)) 0.5))
(cond
[wall? 'wall]
[water? 'water]
[tree? 'tree]
[else empty])))
(hash-set! tiles (list x y) new-tile)
; Sometimes, generate a new enemy
; Only if the new tile is walkable
(when (and (thing-get new-tile 'walkable)
(< (random 100) 1))
(define new-thing
(make-thing
; Base it off a randomly chosend enemy
(vector-ref random-enemies
(random (vector-length random-enemies)))
; This is its location
[location (pt x y)]))
; Store it in the npc list
(set! npcs (cons new-thing npcs))))
; Return the tile (newly generated or not)
(hash-ref tiles (list x y)))
; Define tile types
(define-thing tile
[walkwble #f]
[character #\space]
[color "black"])
(define-thing empty tile
[walkable #t])
(define-thing wall tile
[character #\#]
[color "white"])
(define-thing water tile
[character #\u00db]
[color "blue"])
(define-thing tree tile
[character #\u0005]
[color "green"])
; Try to move an entity to a given location
(define/public (try-move entity target)
(define tile (send this get-tile (pt-x target) (pt-y target)))
(define others
(filter
; Only get ones at the target location that aren't me
(lambda (thing) (and (not (eqv? thing entity))
(= (thing-get thing 'location) target)))
; Include the player and all npcs
(cons player npcs)))
(cond
; If it's not walkable, do nothing
[(not (thing-get tile 'walkable))
(void)]
; If it's walkable and not occupied, update the location
[(null? others)
(thing-set! entity 'location target)]
; If it's walkable and occupied, attack the occupant and don't move
; damage = max(0, rand(min(1, attack)) - rand(min(1, defense)))
[else
(for ([other (in-list others)])
; Do the damage
(define damage
(max 0 (- (random (max 1 (thing-get entity 'attack)))
(random (max 1 (thing-get other 'defense))))))
(thing-set! other 'health (- (thing-get other 'health) damage))
; Log a message
(send this log
(format "~a attacked ~a, did ~a damage"
(thing-get entity 'name)
(thing-get other 'name)
damage)))]))
; Store a list of non-player entities
(define npcs '())
(define/public (update-npcs)
; Allow each to move
(for ([npc (in-list npcs)])
(thing-call npc 'act npc this))
; Check for (and remove) any dead npcs
(set! npcs
(filter
(lambda (npc)
(when (<= (thing-get npc 'health) 0)
(send this log (format "~a has died" (thing-get npc 'name))))
(> (thing-get npc 'health) 0))
npcs)))
(define/public (draw-npcs canvas)
(for ([npc (in-list npcs)])
(define x/y (recenter canvas (- (thing-get player 'locatio)
(thing-get npc 'location))))
(when (and (<= 0 (pt-x x/y) (sub1 (send canvas get-width-in-character)))
(<= 0 (pt-y x/y) (sub1 (send canvas get-height-in-character))))
(send canvas write
(thing-get npc 'character)
(pt-x x/y)
(pt-y x/y)
(thing-get npc 'color)))))
(super-new)))
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化