Nyaatrap

アダルト百合ゲー開発ブログ。一部記事は18歳未満閲覧禁止です。

Home どれぱら デーモンマスタークリス 商用ゲーム フリーゲーム

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

Dungeon Crawl RPG Framework 2.0

Clipboard 1

デーモンマスタークリス等で使われている擬似3DダンジョンRPGのプログラムの簡易版です。
以前公開したプログラムと根本は同じですが、より実用的に修正しました。
1と0の配列で作られたマップの中を徘徊することができ、エンカウントバトルもする他、オートマッピング機能もついてます。
Ren'py 専用ですが、シンプルなプログラムですので、他のゲームエンジンに移植することも可能です。

サンプルゲームをアップロードしましたので、自由に改良して使ってください。
コードはパブリックドメインです。
ダウンロード: http://www.mediafire.com/download/9fli08flzrous1a/Dungeon_Crawl-2.0-all.zip

以下にコードの全てを記しておきます。
コメントは全て英文ですが、需要があれば後ほど日本語にしようと思います。

script.rpy
# This file is in the public domain.

label start:

# Initializing data
python:

# Create skills (name, type, hit, power)
attack = Skill("Attack", "attack", 70, 20)
escape = Skill("Escape", "escape")

# Create battle actors (name, max_hp, skills)
hero = Actor("Hero",100, [attack,escape])
goblin = Actor("Goblin",40, [attack])

# Create a dungeon stage (map,enemy)
# "1" means wall, "0" means path.
stage1=Stage([
"1111111111",
"1111011001",
"1000000001",
"1110111101",
"1000000001",
"1111111111",
],
enemy=goblin)

# The game starts here.

# Place a player position on a dungeon stage (stage,y,x,dy,dx).
# dx,dy means direction. If dy=1, it's down. If dx=-1, it's left.
$ here=Coordinate(stage1,2,2,0,1)

# To start exploring, call or jump to the label dungeon.
call dungeon

# To start battling, call the label battle with 2 actor objects: player and enemy.
call battle(hero,goblin)

dungeon.rpy
# This file is in the public domain.

init -1 python:

class Stage(object):

'''
Class which contains map itself, auto mapping record, and encounter enemy.
'''

def __init__(self, map, enemy=None):
self.map=map
self.enemy=enemy
self.mapped=[]
for n,i in enumerate(map):
self.mapped.append([])
for j in i:
self.mapped[n].append(0)

class Coordinate(object):

'''
Class used for calculating relative coordinate.
'''

def __init__(self, stage=None, y=0, x=0, dy=0, dx=0):
self.stage=stage
self.y=y
self.x=x
self.dy=dy
self.dx=dx

class Minimap(object):

'''
A minimap. Minimap(current_coordinate).sm is a displayable to show this minimap.
'''

def __init__(self,child):
self.sm = SpriteManager(ignore_time=True)
for i in xrange(len(child.stage.map)):
for j in xrange(len(child.stage.map[0])):
if child.stage.mapped[i][j]==1:
if child.stage.map[i][j] in ["1"]:
d = Solid("#666", xysize=(12,12))
else:
d = Solid("#fff9", xysize=(12,12))
else:
d = Solid("#0000", xysize=(12,12))
self.add(d,i,j)
if child.dy==-1:
self.add(Text("↑",size=12),child.y,child.x)
elif child.dx==1:
self.add(Text("→",size=12),child.y,child.x)
elif child.dy==1:
self.add(Text("↓",size=12),child.y,child.x)
else:
self.add(Text("←",size=12),child.y,child.x)

def add(self, d,n,m):
s = self.sm.create(d)
s.x = m*12+12
s.y = n*12+12

screen move:
# Screen which shows move buttons and a minimap

fixed style_group "move":
if front1.stage.map[front1.y][front1.x] is not "1":
textbutton "↑" action Return(value=front1) xcenter .2 ycenter .7
textbutton "→" action Return(value=turnright) xcenter .3 ycenter .8
textbutton "↓" action Return(value=turnback) xcenter .2 ycenter .9
textbutton "←" action Return(value=turnleft) xcenter .1 ycenter .8

add Minimap(here).sm

style move_button_text:
size 60

# Assign background images.
# "left0" means a wall on the lefthand, "front2" means a further wall on the front, and so on.

# left2, front2, right2
# left1, front1, right1
# left0, here , right0

image floor = "floor.png"
image left0 = "left0.png"
image right0 = Transform("left0.png", xzoom=-1)
image front1 ="front1.png"
image left1 = "left1.png"
image right1 = Transform("left1.png", xzoom=-1)
image front2 = "front2.png"
image left2 = "left2.png"
image right2 = Transform("left2.png", xzoom=-1)

label dungeon:
# To start exploring, call or jump to this label
# To exit, create an event which has return or jump statement.

while True:
# Calculate relative coordinates
python:
turnright=Coordinate(here.stage, here.y,here.x, here.dx,-here.dy)
turnleft=Coordinate(here.stage, here.y, here.x, -here.dx,here.dy)
turnback=Coordinate(here.stage, here.y,here.x, -here.dy,-here.dx)
right0=Coordinate(here.stage, here.y+here.dx,here.x-here.dy, here.dy,here.dx)
left0=Coordinate(here.stage, here.y-here.dx,here.x+here.dy, here.dy,here.dx)
front1=Coordinate(here.stage, here.y+here.dy,here.x+here.dx, here.dy,here.dx)
right1=Coordinate(here.stage, front1.y+front1.dx,front1.x-front1.dy, here.dy,here.dx)
left1=Coordinate(here.stage, front1.y-front1.dx,front1.x+front1.dy, here.dy,here.dx)
front2=Coordinate(here.stage, front1.y+front1.dy,front1.x+front1.dx, here.dy,here.dx)
right2=Coordinate(here.stage, front2.y+front2.dx,front2.x-front2.dy, here.dy,here.dx)
left2=Coordinate(here.stage, front2.y-front2.dx,front2.x+front2.dy, here.dy,here.dx)

# Composite background images. Try-except clauses are used to prevent the List Out of Index Error
scene
show floor
python:
for i in ["left2", "right2", "front2", "left1", "right1", "front1", "left0", "right0"]:
try:
j=globals()[i]
if j.stage.map[j.y][j.x]=="1":
renpy.show(i)
except:
pass

# Record maps
python:
for i in [left1, right1, front1, left0, right0, here]:
here.stage.mapped[i.y][i.x]=1

# Check events. If it happnes, call a label or jump out to a label.
if here.stage.enemy is not None and renpy.random.random()< .2:
call battle(player=hero, enemy=here.stage.enemy)

# Otherwise, call the move screen
$ renpy.block_rollback()
call screen move
$ here=_return

battle.rpy
# This file is in the public domain.

init -1 python:

from copy import copy

class Skill(object):

'''
Class used for battle skills
'''

def __init__(self, name, type, hit=0, power=0):
self.name = name
self.type = type
self.hit = hit
self.power = power

class Actor(object):

'''
Class used for battle characters.
'''

def __init__(self, name, max_hp=0, skills=[]):
self.name=name
self.max_hp=max_hp
self.hp=max_hp
self.skills = skills

def attack(self,skill,target):
if self.skill.hit < renpy.random.randint (0,100):
narrator ("{} dodged {}'s attack".format(target.name,self.name))
else:
target.hp -= self.skill.power
narrator ("{} got {} damage".format(target.name, self.skill.power))

screen battle_ui:
# Screen which shows battle status

use battle_frame(char=player, position=(.95,.05))
use battle_frame(char=enemy, position=(.05,.05))

screen battle_frame(char,position):
# Screen included in the battle_ui screen

frame xysize(180, 80) align position:
vbox yfill True:
text "[char.name]"
hbox xfill True:
text "HP"
text "[char.hp]/[char.max_hp]" xalign 1.0

screen command_screen:
# Screen used for selecting skills

vbox style_group "skill" align (.1,.8):
for i in player.skills:
textbutton "[i.name]" action Return (value=i)

style skill_button_text:
size 40
xminimum 200

label battle(player, enemy):
# To start battling, call this label with 2 actor objects: player and enemy.

# Preparation
# Copying enemy object prevents modifying an original data.
$ enemy=copy(enemy)
$ _rollback=False
show screen battle_ui
"[enemy.name] appeared"

# Main phase
call _battle(player, enemy)

# Result
if _return is "lose":
"Gameover"
$renpy.full_restart()
elif _return is "win":
"You won"
elif _return is "escape":
"You escaped"
hide screen battle_ui
$ _rollback=True
return

label _battle(player, enemy):
# A sub label used in the battle label.

while True:
$ player.skill = renpy.call_screen("command_screen")
$ enemy.skill = renpy.random.choice(enemy.skills)
if player.skill.type=="escape":
return "escape"
$ player.attack(player.skill, enemy)
if enemy.hp < 1:
return "win"
$ enemy.attack(enemy.skill, player)
if player.hp < 1:
return "lose"

コメント

コメントの投稿


管理者にだけ表示を許可する

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。