|
 |
|
2016/3/4(Fri) 15:22:38|NO.74768
HSPに関係があるかどうか怪しい質問なのですが、
自分が他に扱える言語が無かったのでひとまずここで質問することにしました。
質問というよりは意見の募集、のような感じですね。
(ということは雑談スレになるのか?これは。)
■本題
皆さんなら、2Dゲームにおいて、オブジェクトの管理・描画処理はどのように作りますか?
敵・味方・設置物・エフェクト・地形・背景(層有り)・弾丸など
全てのモノが関連して描画順を自由に変えられるようにしたいのですが、
何が何だか全く分からない状態なので、皆さんの意見を参考にさせて頂けませんか?
■※
オブジェクト:
本来の意味(?)ではなく、キャラクターとか何かそれっぽいものをひっくるめて
自分はオブジェクトと呼んでいます。
描画処理+補足:
自分はes_excopyを主軸に使っています。
(gmode+gcopy+gzoom+grotateみたいなヤツ)
知識量:
IT系の知識は皆無、
数学は一応辛うじてギリギリ何とか、高2までの内容を理解でき……ます(たぶん)。
■以下長い
現在自分は、STGゲームを作るのに様々な配列変数を用意しています。
scrl(背景用)
bgobj(背景演出用)
bgobjani~(アニメーション用の諸変数)
bgobjlayer(bgobj内の描画順)
obj(主に当たり判定を持つキャラクターや地形・設置物)
objani~
objlayer
blt(弾丸用)
ptcl(エフェクト用)など
このような感じで管理していたのですが、
背景スクロールとオブジェクトなどが完全に別々で処理・動作・描写していて
描画順を変えることが出来ないのです。
オブジェクト同士の描画順もソートの処理が重そうで怖いので、
事前に振り分けておいた描画順を、
repeat10:if objlayer()=cnt{描画}:loopして描画順を作ってる状況です。
ひょっとしなくても、
全てobj~みたいな配列変数で管理して、描画時にzソートのような何かを利用して
描画するのが一般的なんだろうなぁと思ったのです。
でも、全て一括管理するとなると、
描画処理とその他各処理をどうやって分けたら良いかよく分からなくなってしまって。
それに、
layer(とかz-index)は何を単位に振り分けたらいいのかすら分からない……
レイヤー10枚くらい用意するか。
それとも、z座標を計算に取り込んで、表示倍率と描画順を一括管理しちゃうか。
z座標なら、距離感(表示倍率・描画順)が簡単に把握できて便利そう。
――そしたらソートはどうなるんだ??
いずれにしろ、
今考えている方法で一括管理するとなると
(僕の場合は)敵味方設置物100個位+弾丸64個位+演出用32個位+エフェクト用+32個位の
配列をソートして描画することになる。
バブルソートしかやり方が分からない僕には、絶望的すぎる。
色々分からないor混乱している事だらけで、どう手を付けていいか分からなくなっています。

| |
|
2016/3/5(Sat) 01:28:12|NO.74780
質問している内容が多岐に渡る為どこから手をつければ良いのかが難しい問題ですが……
とりあえず気になった点だけでも羅列しておきますね
・昨今のゲームプログラミング事情的には2Dゲームであっても3D描画を使うのが一般的かと思います
HSPにおいてもHGIMG3やHGIMG4などを検討してみても悪くないかと思います
これは処理速度の面においても断然有利ですが、
画面更新という考え方から「描画オブジェクト」という考え方に変わる事で
オブジェクトの多いゲームにおいて全体をスッキリさせやすくなったりします
・配列変数含め変数名の命名ルールを適当に持っておいたほうが良さそうです
例:objBG objBlt flgBGAni など
このまま突き進むといつかスパゲティ化が激化し自分でも難読になりますので
「変数の命名ルールを作る」か「変数の説明をコメントに書いておく」
などの対応は今のうちしておいたほうが楽になりますよ
・ここまで出来ている方なら断然クイックソートを前向きに検討すべきです
「なんで速いの」を無視すれば実装は結構簡単です だもんでググれば幾つも出ry
実装時に「配列変数の中身は入れ替えず結果の位置だけ取得出来るようにする」事で
「ソートのキーにする配列変数に対しクイックソート」->
「他の配列変数は結果の位置を見ながら参照」とする事でソート回数は1回に出来ますよ
また「ソートはあくまでZ-Index関連でしか使わない」のであれば
「Z-Indexに関わる全てのオブジェクトを同一の配列変数に保持し、
それらの種別などの配列変数を持つ」などといった運用をオススメします
……あ、ここまで書いておいて何ですがZ-Indexの管理運用はクソ面倒だと思うので
やはり何らかの3D描画を利用した上で
「0.001」とか分からないくらいZ軸をズラすという姑息な手段をオススメしておきます……w
HGIMG3だとオブジェクト登録順になったような??これでも楽ですね
|
|
2016/3/6(Sun) 19:49:05|NO.74800
> ひょっとしなくても、
> 全てobj~みたいな配列変数で管理して、描画時にzソートのような何かを利用して
> 描画するのが一般的なんだろうなぁと思ったのです。
モジュール型変数を使えばよいと思います。
//------------------------------------------------------------------------------
// モジュール型変数によるシューティング・ゲーム
//==============================================================================
// 新規作成日:2013-06-10 (月) 18:28:00
// 最終更新日:2013-06-10 (月) 22:58:00
// 最終更新日:2013-06-11 (火) 03:48:00
// 最終更新日:2013-06-11 (火) 04:36:00
//------------------------------------------------------------------------------
#packopt name __FILE__
//--------------------------------------
// HSP命令/関数の記号定数
//--------------------------------------
#const global STICK_LEFT ($0001)
#const global STICK_UP ($0002)
#const global STICK_RIGHT ($0004)
#const global STICK_DOWN ($0008)
#const global STICK_SPACE ($0010)
#const global STICK_ENTER ($0020)
#const global STICK_CTRL ($0040)
#const global STICK_ESC ($0080)
#const global STICK_LMOUSE ($0100)
#const global STICK_RMOUSE ($0200)
#const global STICK_TAB ($0400)
#const global STICK_SCAN (STICK_UP|STICK_DOWN|STICK_LEFT|STICK_RIGHT)
//--------------------------------------
// ゲーム全体の記号定数
//--------------------------------------
#const global MAX_LEFT (10) ;自機の最大残り数
#const global MAX_BOMB (10) ;自機の最大ボム数
#const global MAX_OPTION (3) ;自機のオプション数
#const global MAX_ITEMTABLE (10) ;敵機のアイテム発生テーブル
#
#const global MAX_FIGHT (MAX_OPTION+1)
#const global MAX_ENEMY (100)
#const global MAX_SHOT (50)
#const global MAX_BEAM (50)
#const global MAX_ITEM (50)
#const global MAX_STAR (100)
#const global MAX_BLAST (100)
#const global MAX_TELOP (5)
//--------------------------------------
// モジュールの記号定数
//--------------------------------------
#const global FPS (60)
#const global FIGHT_XSIZE (32/2)
#const global FIGHT_YSIZE (32/2)
#const global FIGHT_SPEED (5)
#const global FIGHT_DELAY (12)
#const global FIGHT_COURSE (FIGHT_DELAY*MAX_OPTION+1)
#
#const global ENEMY_XSIZE (32/2)
#const global ENEMY_YSIZE (32/2)
#const global ENEMY_SPEED (2)
#const global ENEMY_BIRTH (FPS/3)
#const global ENEMY_SCORE (10)
#
#const global BLAST_XSIZE (32/2)
#const global BLAST_YSIZE (32/2)
#const global BLAST_ANIME (12)
#const global BLAST_BLINK (4)
#const global BLAST_COUNT (FPS/BLAST_ANIME)
#
#const global SHOT_XSIZE (6/2)
#const global SHOT_YSIZE (6/2)
#const global SHOT_SPEED (10)
#
#const global BEAM_XSIZE (4/2)
#const global BEAM_YSIZE (32/2)
#const global BEAM_SPEED (5)
#
#const global ITEM_XSIZE (32/2)
#const global ITEM_YSIZE (32/2)
#const global ITEM_SPEED (1)
#
#const global STAR_BIRTH (FPS/60)
//--------------------------------------
// ゲーム画面の記号定数
//--------------------------------------
#const global DISP_WIDTH (640)
#const global DISP_HEIGHT (480)
#
#const global DEATH_MARGIN (50)
#const global DEATH_LEFT (-DEATH_MARGIN)
#const global DEATH_TOP (-DEATH_MARGIN)
#const global DEATH_RIGHT (DISP_WIDTH+DEATH_MARGIN)
#const global DEATH_BOTTOM (DISP_HEIGHT+DEATH_MARGIN)
#
#const global FIGHT_LEFT (FIGHT_XSIZE)
#const global FIGHT_RIGHT (DISP_WIDTH-FIGHT_XSIZE-1)
#const global FIGHT_TOP (FIGHT_YSIZE)
#const global FIGHT_BOTTOM (DISP_HEIGHT-FIGHT_YSIZE-1)
//--------------------------------------
// テロップの記号定数
//--------------------------------------
#const global FONT_SIZE (20)
#const global HALF_SIZE (FONT_SIZE/2)
#
#const global ALIVE_SIZE (HALF_SIZE*12)
#const global FLUSH_SIZE (HALF_SIZE*7)
#const global SCORE_SIZE (HALF_SIZE*14)
#const global HISCORE_SIZE (HALF_SIZE*16)
#
#const global ALIVE_CX (DISP_WIDTH-ALIVE_SIZE)/2
#const global ALIVE_CY (0)
#const global FIGHT_CX (HALF_SIZE*2)
#const global FIGHT_CY (DISP_HEIGHT-FONT_SIZE)
#const global FLUSH_CX (DISP_WIDTH-HALF_SIZE*3-FLUSH_SIZE)
#const global FLUSH_CY (DISP_HEIGHT-FONT_SIZE)
#const global SCORE_CX (HALF_SIZE*2)
#const global SCORE_CY (0)
#const global HISCORE_CX (DISP_WIDTH-HALF_SIZE*3-HISCORE_SIZE)
#const global HISCORE_CY (0)
//--------------------------------------
// 自機タイプの列挙定数
//--------------------------------------
#enum global FIGHT_NORMAL=0
#enum global FIGHT_OPTION
//--------------------------------------
// 爆風タイプの列挙定数
//--------------------------------------
#enum global BLAST_NULL=0
#enum global BLAST_FIGHT
#enum global BLAST_ITEM
//--------------------------------------
// 流星カラーの列挙定数
//--------------------------------------
#enum global COLOR_BLACK=0
#enum global COLOR_RED
#enum global COLOR_GREEN
#enum global COLOR_YELLOW
#enum global COLOR_BLUE
#enum global COLOR_PURPLE
#enum global COLOR_CYAN
#enum global COLOR_WHITE
//--------------------------------------
// アイテムの列挙定数
//--------------------------------------
#enum global ITEMS_NULL=0
#enum global ITEMS_LEFT
#enum global ITEMS_BOMB
#enum global ITEMS_FLUSH
#enum global ITEMS_SCORE
#enum global ITEMS_OPTION
//--------------------------------------
// テロップの列挙定数
//--------------------------------------
#enum global TELOP_FIGHT=0
#enum global TELOP_FLUSH
#enum global TELOP_SCORE
#enum global TELOP_HISCORE
#enum global TELOP_ALIVE
//--------------------------------------
// テロップの更新定数
//--------------------------------------
#const global REDRAW_FIGHT (1<<TELOP_FIGHT)
#const global REDRAW_FLUSH (1<<TELOP_FLUSH)
#const global REDRAW_SCORE (1<<TELOP_SCORE)
#const global REDRAW_HISCORE (1<<TELOP_HISCORE)
#const global REDRAW_ALIVE (1<<TELOP_ALIVE)
//--[自機クラス]----------------------------------------------------------------
#module FightClass m_cx,m_cy,m_type
//--------------------------------------
// 自機の発生
//--------------------------------------
#modinit int _cx_,int _cy_,int _type_
m_cx=_cx_
m_cy=_cy_
m_type=_type_
return
//--------------------------------------
// 自機の移動
//--------------------------------------
#modfunc FightMove int _key_
if(_key_ & STICK_LEFT) :m_cx-=FIGHT_SPEED:if(m_cx<FIGHT_LEFT) :m_cx=FIGHT_LEFT
if(_key_ & STICK_RIGHT) :m_cx+=FIGHT_SPEED:if(m_cx>FIGHT_RIGHT) :m_cx=FIGHT_RIGHT
if(_key_ & STICK_UP) :m_cy-=FIGHT_SPEED:if(m_cy<FIGHT_TOP) :m_cy=FIGHT_TOP
if(_key_ & STICK_DOWN) :m_cy+=FIGHT_SPEED:if(m_cy>FIGHT_BOTTOM) :m_cy=FIGHT_BOTTOM
return
//--------------------------------------
// 自機の描画
//--------------------------------------
#modfunc FightDraw
switch m_type
case FIGHT_NORMAL
color $00,$FF,$00:boxf (m_cx-FIGHT_XSIZE),(m_cy-FIGHT_YSIZE),(m_cx+FIGHT_XSIZE),(m_cy+FIGHT_YSIZE)
swbreak
case FIGHT_OPTION
color $FF,$CC,$00:circle (m_cx-FIGHT_XSIZE),(m_cy-FIGHT_YSIZE),(m_cx+FIGHT_XSIZE),(m_cy+FIGHT_YSIZE),1
color $CC,$99,$00:circle (m_cx-FIGHT_XSIZE),(m_cy-FIGHT_YSIZE),(m_cx+FIGHT_XSIZE),(m_cy+FIGHT_YSIZE),0
swbreak
swend
return
//--------------------------------------
// 自機の現在位置を設定
//--------------------------------------
#modfunc FightSetCurs int _cx_,int _cy_
m_cx=_cx_
m_cy=_cy_
return
//--------------------------------------
// 自機の現在位置を取得
//--------------------------------------
#modfunc FightGetCurs var _cx_,var _cy_
_cx_=m_cx
_cy_=m_cy
return
//--------------------------------------
// 自機の矩形領域を取得
//--------------------------------------
#modfunc FightGetRect var _cx_,var _cy_,var _ex_,var _ey_
_cx_=(m_cx-FIGHT_XSIZE)
_cy_=(m_cy-FIGHT_YSIZE)
_ex_=(m_cx+FIGHT_XSIZE)
_ey_=(m_cy+FIGHT_YSIZE)
return
//--------------------------------------
// 自機の破壊
//--------------------------------------
#modfunc FightCrash var _cx_,var _cy_,var _type_
_cx_=m_cx
_cy_=m_cy
_type_=m_type
delmod thismod
return
#global
//--[敵機クラス]----------------------------------------------------------------
#module EnemyClass m_cx,m_cy,m_beam,m_item
//--------------------------------------
// 敵機の発生
//--------------------------------------
#modinit int _cx_,int _cy_,int _item_
m_cx=_cx_
m_cy=_cy_
m_beam=rnd(50)+10 ;ビームの発射間隔
m_item=_item_
return
//--------------------------------------
// 敵機の移動
//--------------------------------------
#modfunc EnemyMove
m_cy+=ENEMY_SPEED
if(m_cy>=DEATH_BOTTOM):delmod thismod
return
//--------------------------------------
// 敵機の描画
//--------------------------------------
#modfunc EnemyDraw
if(m_item):color $FF,$00,$FF:else:color $00,$FF,$FF
boxf (m_cx-ENEMY_XSIZE),(m_cy-ENEMY_YSIZE),(m_cx+ENEMY_XSIZE),(m_cy+ENEMY_YSIZE)
return
//--------------------------------------
// 敵機のビーム発射
//--------------------------------------
#modfunc EnemyShot var _cx_,var _cy_
_cx_=m_cx
_cy_=m_cy
m_beam--
return (m_beam==0)
//--------------------------------------
// 敵機の矩形領域を取得
//--------------------------------------
#modfunc EnemyGetRect var _cx_,var _cy_,var _ex_,var _ey_
_cx_=(m_cx-ENEMY_XSIZE)
_cy_=(m_cy-ENEMY_YSIZE)
_ex_=(m_cx+ENEMY_XSIZE)
_ey_=(m_cy+ENEMY_YSIZE)
return
//--------------------------------------
// 敵機の当たり判定
//--------------------------------------
#modfunc EnemyCheck int _cx_,int _cy_,int _ex_,int _ey_
n=0
repeat 1
if(_ex_<=(m_cx-ENEMY_XSIZE)):break
if(_ey_<=(m_cy-ENEMY_YSIZE)):break
if(_cx_>=(m_cx+ENEMY_XSIZE)):break
if(_cy_>=(m_cy+ENEMY_YSIZE)):break
n=1
loop
return n
//--------------------------------------
// 敵機の破壊
//--------------------------------------
#modfunc EnemyCrash var _cx_,var _cy_,var _item_
_cx_=m_cx
_cy_=m_cy
_item_=m_item
delmod thismod
return ENEMY_SCORE
#global
//--[自機弾クラス]--------------------------------------------------------------
#module ShotClass m_cx,m_cy
//--------------------------------------
// 自機弾の発生
//--------------------------------------
#modinit int _cx_,int _cy_
m_cx=_cx_
m_cy=_cy_
return
//--------------------------------------
// 自機弾の移動
//--------------------------------------
#modfunc ShotMove
m_cy-=SHOT_SPEED
if(m_cy<DEATH_TOP):delmod thismod
return
//--------------------------------------
// 自機弾の描画
//--------------------------------------
#modfunc ShotDraw
color $FF,$FF,$00
circle (m_cx-SHOT_XSIZE),(m_cy-SHOT_YSIZE),(m_cx+SHOT_XSIZE),(m_cy+SHOT_YSIZE)
return
//--------------------------------------
// 自機弾の当たり判定
//--------------------------------------
#modfunc ShotCheck int _cx_,int _cy_,int _ex_,int _ey_
n=0
repeat 1
if(_ex_<=(m_cx-SHOT_XSIZE)):break
if(_ey_<=(m_cy-SHOT_YSIZE)):break
if(_cx_>=(m_cx+SHOT_XSIZE)):break
if(_cy_>=(m_cy+SHOT_YSIZE)):break
delmod thismod
n=1
loop
return n
#global
//--[敵機弾クラス]--------------------------------------------------------------
#module BeamClass m_cx,m_cy
//--------------------------------------
// 敵機弾の発生
//--------------------------------------
#modinit int _cx_,int _cy_
m_cx=_cx_
m_cy=_cy_
return
//--------------------------------------
// 敵機弾の移動
//--------------------------------------
#modfunc BeamMove
m_cy+=BEAM_SPEED
if(m_cy>=DEATH_BOTTOM):delmod thismod
return
//--------------------------------------
// 敵機弾の描画
//--------------------------------------
#modfunc BeamDraw
color $FF,$FF,$00
boxf (m_cx-BEAM_XSIZE),(m_cy-BEAM_YSIZE),(m_cx+BEAM_XSIZE),(m_cy+BEAM_YSIZE)
return
//--------------------------------------
// 敵機弾の当たり判定
//--------------------------------------
#modfunc BeamCheck int _cx_,int _cy_,int _ex_,int _ey_
n=0
repeat 1
if(_ex_<=(m_cx-BEAM_XSIZE)):break
if(_ey_<=(m_cy-BEAM_YSIZE)):break
if(_cx_>=(m_cx+BEAM_XSIZE)):break
if(_cy_>=(m_cy+BEAM_YSIZE)):break
delmod thismod
n=1
loop
return n
//--------------------------------------
// 敵機弾の破壊
//--------------------------------------
#modfunc BeamCrash var _cx_,var _cy_
_cx_=m_cx
_cy_=m_cy
delmod thismod
return
#global
//--[アイテム・クラス]----------------------------------------------------------
#module ItemClass m_cx,m_cy,m_item
//--------------------------------------
// アイテムの発生
//--------------------------------------
#modinit int _cx_,int _cy_,int _item_
m_cx=_cx_
m_cy=_cy_
m_item=_item_
return
//--------------------------------------
// アイテムの移動
//--------------------------------------
#modfunc ItemMove
m_cy+=ITEM_SPEED
if(m_cy>DEATH_BOTTOM):delmod thismod
return
//--------------------------------------
// アイテムの描画
//--------------------------------------
#modfunc ItemDraw
switch m_item
case ITEMS_LEFT: r=$FF:g=$FF:b=$FF:s="UP":swbreak
case ITEMS_BOMB: r=$FF:g=$FF:b=$00:s="B":swbreak
case ITEMS_FLUSH: r=$FF:g=$FF:b=$00:s="*":swbreak
case ITEMS_SCORE: r=$FF:g=$FF:b=$FF:s="S":swbreak
case ITEMS_OPTION: r=$FF:g=$CC:b=$00:s="O":swbreak
default: r=$00:g=$00:b=$00:s=" ":swbreak
swend
color r,g,b:boxf (m_cx-ITEM_XSIZE),(m_cy-ITEM_YSIZE),(m_cx+ITEM_XSIZE),(m_cy+ITEM_YSIZE)
r=r*60/100
g=g*60/100
b=b*60/100
color r,g,b:pos (m_cx-ITEM_XSIZE),(m_cy-ITEM_YSIZE):mes s
return
//--------------------------------------
// アイテムの当たり判定
//--------------------------------------
#modfunc ItemCheck int _cx_,int _cy_,int _ex_,int _ey_
n=0
repeat 1
if(_ex_<=(m_cx-ITEM_XSIZE)):break
if(_ey_<=(m_cy-ITEM_YSIZE)):break
if(_cx_>=(m_cx+ITEM_XSIZE)):break
if(_cy_>=(m_cy+ITEM_YSIZE)):break
n=1
loop
return n
//--------------------------------------
// アイテムの消滅
//--------------------------------------
#modfunc ItemCrash var _cx_,var _cy_,var _item_
_cx_=m_cx
_cy_=m_cy
_item_=m_item
delmod thismod
return 0
#global
//--[流星クラス]----------------------------------------------------------------
#module StarClass m_cx,m_cy,m_color,m_speed
//--------------------------------------
// 流星の発生
//--------------------------------------
#modinit
m_cx=rnd(DISP_WIDTH)
m_cy=0
m_color=rnd(COLOR_WHITE)+1
m_speed=rnd(5)+2
return
//--------------------------------------
// 流星の移動
//--------------------------------------
#modfunc StarMove
m_cy+=m_speed
if(m_cy>=DEATH_BOTTOM):delmod thismod
return
//--------------------------------------
// 流星の描画
//--------------------------------------
#modfunc StarDraw
switch m_color
case COLOR_BLACK: color $00,$00,$00:swbreak
case COLOR_RED: color $FF,$00,$00:swbreak
case COLOR_GREEN: color $00,$FF,$00:swbreak
case COLOR_YELLOW: color $FF,$FF,$00:swbreak
case COLOR_BLUE: color $00,$00,$FF:swbreak
case COLOR_PURPLE: color $FF,$00,$FF:swbreak
case COLOR_CYAN: color $00,$FF,$FF:swbreak
case COLOR_WHITE: color $FF,$FF,$FF:swbreak
swend
pset m_cx,m_cy
return
#global
//--[爆風クラス]----------------------------------------------------------------
#module BlastClass m_cx,m_cy,m_count,m_anime,m_type,m_data
//--------------------------------------
// 爆風の発生
//--------------------------------------
#modinit int _cx_,int _cy_,int _type_,int _data_
m_cx=_cx_
m_cy=_cy_
m_count=BLAST_COUNT
m_anime=BLAST_ANIME
m_type=_type_
m_data=_data_
return
//--------------------------------------
// 爆風のアニメ
//--------------------------------------
#modfunc BlastMove var _cx_,var _cy_,var _data_
m_count--
if(m_count==0){
m_count=BLAST_COUNT
m_anime--
}
if(m_anime==0){
_cx_=m_cx
_cy_=m_cy
_data_=m_data
n=m_type
delmod thismod
return n
}
return 0
//--------------------------------------
// 爆風の描画
//--------------------------------------
#modfunc BlastDraw
cx=(m_cx-BLAST_XSIZE)
cy=(m_cy-BLAST_YSIZE)
ex=(m_cx+BLAST_XSIZE)
ey=(m_cy+BLAST_YSIZE)
n=(BLAST_ANIME-m_anime)*2
cx+=n
cy+=n
ex-=n-1
ey-=n-1
r=$FF:g=$66:b=$33
repeat n
r=r*90/100
g=g*90/100
b=b*90/100
loop
color r,g,b
circle cx,cy,ex,ey
return
#global
//--[テロップ・クラス]----------------------------------------------------------
#module TelopClass m_cx,m_cy,m_color,m_msg
//--------------------------------------
// テロップの発生
//--------------------------------------
#modinit int _cx_,int _cy_,int _color_,str _msg_
m_cx=_cx_
m_cy=_cy_
m_color=_color_
m_msg=_msg_
return
//--------------------------------------
// テロップの描画
//--------------------------------------
#modfunc TelopDraw
n=$33
repeat 3
if(m_color & $01):r=n:else:r=$00
if(m_color & $02):g=n:else:g=$00
if(m_color & $04):b=n:else:b=$00
color r,g,b
pos (m_cx+2-cnt),(m_cy+2-cnt)
mes m_msg
n+=$66
loop
return
//--------------------------------------
// テロップの文字列を設定
//--------------------------------------
#modfunc TelopSetMsg str _msg_
m_msg=_msg_
return
#global
//--[メイン部]------------------------------------------------------------------
//--------------------------------------
// グローバル変数
//--------------------------------------
#define Score gValue(0)
#define HiScore gValue(1)
#define FightLeft gValue(2)
#define FightBomb gValue(3)
#define FightAlive gValue(4)
#define FightOption gValue(5)
#define TelopRedraw gValue(6)
#define StarBirthCycle gValue(7)
#define EnemyBirthCycle gValue(8)
#
#define key gValue(9)
#define n gValue(10)
#define x gValue(11)
#define y gValue(12)
#define cx gValue(13)
#define cy gValue(14)
#define ex gValue(15)
#define ey gValue(16)
dim gValue,17
//--------------------------------------
// メイン部
//--------------------------------------
*Init
; dim Score
; dim HiScore
; dim FightLeft
; dim FightBomb
; dim FightAlive
; dim FightOption
; dim TelopRedraw
; dim StarBirthCycle
; dim EnemyBirthCycle
dim FightCourseX,FIGHT_COURSE
dim FightCourseY,FIGHT_COURSE
dim EnemyItemTable,MAX_ITEMTABLE
*Main
randomize
title "モジュール型変数によるシューティング・ゲーム"
screen 0,DISP_WIDTH,DISP_HEIGHT
font MSGOTHIC,FONT_SIZE,1
gosub *ShootingInit
repeat
redraw 0
stick key,STICK_SCAN
gosub *ShootingMove
gosub *ShootingDraw
redraw 1
await (1000/FPS)
loop
stop
//--------------------------------------
// シューティングの初期化
//--------------------------------------
*ShootingInit
dimtype Fight, vartype("struct"),MAX_FIGHT
dimtype Enemy, vartype("struct"),MAX_ENEMY
dimtype Shot, vartype("struct"),MAX_SHOT
dimtype Beam, vartype("struct"),MAX_BEAM
dimtype Item, vartype("struct"),MAX_ITEM
dimtype Star, vartype("struct"),MAX_STAR
dimtype Blast, vartype("struct"),MAX_BLAST
dimtype Telop, vartype("struct"),MAX_TELOP
gosub *FightInit
gosub *EnemyInit
gosub *TelopInit
return
//--------------------------------------
// シューティングの移動
//--------------------------------------
*ShootingMove
gosub *FightMoveAll
gosub *EnemyMoveAll
gosub *ShotMoveAll
gosub *BeamMoveAll
gosub *ItemMoveAll
gosub *StarMoveAll
gosub *BlastMoveAll
gosub *CrashMainAll
return
//--------------------------------------
// シューティングの描画
//--------------------------------------
*ShootingDraw
color $00,$00,$00:boxf
gosub *StarDrawAll
gosub *ShotDrawAll
gosub *BeamDrawAll
gosub *ItemDrawAll
gosub *EnemyDrawAll
gosub *FightDrawAll
gosub *BlastDrawAll
gosub *TelopDrawAll
return
//--------------------------------------
// 全体の当たり判定
//--------------------------------------
*CrashMainAll
if(varuse(Fight(0))){
FightGetRect Fight(0),cx,cy,ex,ey
// 自機⇒敵機,敵機弾
if(EnemyCheckAll(cx,cy,ex,ey)||BeamCheckAll(cx,cy,ex,ey)){
if(FightAlive==0){
gosub *FightCrashAll
}
}
// 自機⇒アイテム
if(ItemCheckAll(cx,cy,ex,ey)){
/* アイテムの衝突音 */
}
}
// 敵機⇒自機弾
foreach Enemy
EnemyGetRect Enemy(cnt),cx,cy,ex,ey
if(ShotCheckAll(cx,cy,ex,ey)){
gosub *EnemyDeath
}
loop
return
//--[自機管理]------------------------------------------------------------------
//--------------------------------------
// 自機全体の初期化
//--------------------------------------
*FightInit
x=(DISP_WIDTH/2)
y=(DISP_HEIGHT-FIGHT_YSIZE-16)
FightBirth x,y
FightLeft=3
FightBomb=5
FightAlive=0
return
//--------------------------------------
// 自機全体の移動
//--------------------------------------
*FightMoveAll
if(varuse(Fight(0))){
// 無敵モード
if(key & STICK_TAB){
FightAlive^=1
TelopRedraw|=REDRAW_ALIVE
}
// デバッグ・モード
if(key & STICK_ESC){
}
// 弾丸の発射
if(key & STICK_SPACE){
foreach Fight
FightGetCurs Fight(cnt),x,y
newmod Shot,ShotClass,x,y
loop
}
// ボムの発射
if(key & STICK_ENTER){
if(FightBomb){
gosub *EnemyFlush
gosub *BeamFlush
FightBomb--
TelopRedraw|=REDRAW_FLUSH
}
}
// 自機の移動
if(key & STICK_SCAN){
// 軌道シフト
repeat FIGHT_COURSE-1
n=(FIGHT_COURSE-1-cnt)
FightCourseX(n)=FightCourseX(n-1)
FightCourseY(n)=FightCourseY(n-1)
loop
// 移動
FightMove Fight(0),key
FightGetCurs Fight(0),x,y
FightCourseX(0)=x
FightCourseY(0)=y
// 設定
foreach Fight
x=FightCourseX(FIGHT_DELAY*cnt)
y=FightCourseY(FIGHT_DELAY*cnt)
FightSetCurs Fight(cnt),x,y
loop
}
}
return
//--------------------------------------
// 自機全体の描画
//--------------------------------------
*FightDrawAll
foreach Fight
FightDraw Fight(cnt)
loop
return
//--------------------------------------
// 自機全体の破壊
//--------------------------------------
*FightCrashAll
foreach Fight
FightCrash Fight(cnt),x,y,n
if(n){
newmod Blast,BlastClass,x,y,BLAST_NULL,0 ;オプションの破壊
}
else{
newmod Blast,BlastClass,x,y,BLAST_FIGHT,0 ;自機の破壊
}
loop
return
//--------------------------------------
// 自機全体の誕生
//--------------------------------------
#deffunc FightBirth int _x_,int _y_
// 軌道シフト
repeat FIGHT_COURSE
FightCourseX(cnt)=_x_
FightCourseY(cnt)=_y_
loop
// 誕生
newmod Fight,FightClass,_x_,_y_,FIGHT_NORMAL
; newmod Fight,FightClass,_x_,_y_,FIGHT_OPTION
; newmod Fight,FightClass,_x_,_y_,FIGHT_OPTION
; newmod Fight,FightClass,_x_,_y_,FIGHT_OPTION
FightOption=0
return
//--------------------------------------
// 自機全体の消滅
//--------------------------------------
#deffunc FightDeath int _cx_,int _cy_
if(FightLeft==0){
dialog "ゲームオーバーです。",1,"確認"
end
}
FightLeft--
FightBirth _cx_,_cy_
TelopRedraw|=REDRAW_FIGHT
return
//--[敵機管理]------------------------------------------------------------------
//--------------------------------------
// 敵機全体の初期化
//--------------------------------------
*EnemyInit
n=-1
n++:EnemyItemTable(n)=ITEMS_LEFT ;20%
n++:EnemyItemTable(n)=ITEMS_LEFT
n++:EnemyItemTable(n)=ITEMS_BOMB ;20%
n++:EnemyItemTable(n)=ITEMS_BOMB
n++:EnemyItemTable(n)=ITEMS_FLUSH ;20%
n++:EnemyItemTable(n)=ITEMS_FLUSH
n++:EnemyItemTable(n)=ITEMS_SCORE ;40%
n++:EnemyItemTable(n)=ITEMS_SCORE
n++:EnemyItemTable(n)=ITEMS_OPTION ;20%
n++:EnemyItemTable(n)=ITEMS_OPTION
return
//--------------------------------------
// 敵機全体の移動
//--------------------------------------
*EnemyMoveAll
// 誕生
EnemyBirthCycle++
if(EnemyBirthCycle>=ENEMY_BIRTH){
x=rnd(DISP_WIDTH-ENEMY_XSIZE*2)+ENEMY_XSIZE
y=-ENEMY_YSIZE
n=0
if(rnd(100)<10){
n=EnemyItemTable(rnd(MAX_ITEMTABLE)) ;10%確率
}
newmod Enemy,EnemyClass,x,y,n
EnemyBirthCycle=0
}
// 移動
foreach Enemy
EnemyShot Enemy(cnt),x,y
if(stat):newmod Beam,BeamClass,x,y
EnemyMove Enemy(cnt)
loop
return
//--------------------------------------
// 敵機全体の描画
//--------------------------------------
*EnemyDrawAll
foreach Enemy
EnemyDraw Enemy(cnt)
loop
return
//--------------------------------------
// 敵機全体の当たり判定
//--------------------------------------
#defcfunc EnemyCheckAll int _cx_,int _cy_,int _ex_,int _ey_
n=0
foreach Enemy
EnemyCheck Enemy(cnt),_cx_,_cy_,_ex_,_ey_
if(stat){
gosub *EnemyDeath
n=1
break
}
loop
return n
//--------------------------------------
// 敵機全体の一掃
//--------------------------------------
*EnemyFlush
foreach Enemy
gosub *EnemyDeath
loop
return
//--------------------------------------
// 敵機一体の破壊
//--------------------------------------
*EnemyDeath
EnemyCrash Enemy(cnt),x,y,n
TelopScore stat
if(n){
newmod Blast,BlastClass,x,y,BLAST_ITEM,n
}
else{
newmod Blast,BlastClass,x,y,BLAST_NULL,0
}
return
//--[自機弾管理]----------------------------------------------------------------
//--------------------------------------
// 自機弾全体の移動
//--------------------------------------
*ShotMoveAll
foreach Shot
ShotMove Shot(cnt)
loop
return
//--------------------------------------
// 自機弾全体の描画
//--------------------------------------
*ShotDrawAll
foreach Shot
ShotDraw Shot(cnt)
loop
return
//--------------------------------------
// 自機弾全体の当たり判定
//--------------------------------------
#defcfunc ShotCheckAll int _cx_,int _cy_,int _ex_,int _ey_
n=0
foreach Shot
ShotCheck Shot(cnt),_cx_,_cy_,_ex_,_ey_
if(stat){
n=1
break
}
loop
return n
//--[敵機弾管理]----------------------------------------------------------------
//--------------------------------------
// 敵機弾全体の移動
//--------------------------------------
*BeamMoveAll
foreach Beam
BeamMove Beam(cnt)
loop
return
//--------------------------------------
// 敵機弾全体の描画
//--------------------------------------
*BeamDrawAll
foreach Beam
BeamDraw Beam(cnt)
loop
return
//--------------------------------------
// 敵機弾全体の当たり判定
//--------------------------------------
#defcfunc BeamCheckAll int _cx_,int _cy_,int _ex_,int _ey_
n=0
foreach Beam
BeamCheck Beam(cnt),_cx_,_cy_,_ex_,_ey_
if(stat){
n=1
break
}
loop
return n
//--------------------------------------
// 敵機弾全体の一掃
//--------------------------------------
*BeamFlush
foreach Beam
BeamCrash Beam(cnt),x,y
newmod Blast,BlastClass,x,y,BLAST_NULL,0
loop
return
//--[アイテム管理]--------------------------------------------------------------
//--------------------------------------
// アイテム全体の移動
//--------------------------------------
*ItemMoveAll
foreach Item
ItemMove Item(cnt)
loop
return
//--------------------------------------
// アイテム全体の描画
//--------------------------------------
*ItemDrawAll
font MSGOTHIC,ITEM_YSIZE*2,1
foreach Item
ItemDraw Item(cnt)
loop
font MSGOTHIC,FONT_SIZE,1
return
//--------------------------------------
// アイテム全体の当たり判定
//--------------------------------------
#defcfunc ItemCheckAll int _cx_,int _cy_,int _ex_,int _ey_
n=0
foreach Item
ItemCheck Item(cnt),_cx_,_cy_,_ex_,_ey_
if(stat){
gosub *ItemDeath
n=1
break
}
loop
return n
//--------------------------------------
// アイテム一体の破壊
//--------------------------------------
*ItemDeath
ItemCrash Item(cnt),x,y,n
TelopScore stat
switch n
case ITEMS_LEFT
if(FightLeft<MAX_LEFT){
FightLeft++
TelopRedraw|=REDRAW_FIGHT
}
swbreak
case ITEMS_BOMB
if(FightBomb<MAX_BOMB){
FightBomb++
TelopRedraw|=REDRAW_FLUSH
}
swbreak
case ITEMS_FLUSH
gosub *EnemyFlush
gosub *BeamFlush
swbreak
case ITEMS_SCORE
TelopScore 1000
swbreak
case ITEMS_OPTION
if(FightOption<MAX_OPTION){
FightOption++
x=FightCourseX(FIGHT_DELAY*FightOption)
y=FightCourseY(FIGHT_DELAY*FightOption)
newmod Fight,FightClass,x,y,FIGHT_OPTION
}
swbreak
default:swbreak
swend
return
//--[流星管理]------------------------------------------------------------------
//--------------------------------------
// 流星全体の移動
//--------------------------------------
*StarMoveAll
// 誕生
StarBirthCycle++
if(StarBirthCycle>=STAR_BIRTH){
newmod Star,StarClass
StarBirthCycle=0
}
// 移動
foreach Star
StarMove Star(cnt)
loop
return
//--------------------------------------
// 流星全体の描画
//--------------------------------------
*StarDrawAll
foreach Star
StarDraw Star(cnt)
loop
return
//--[爆風管理]------------------------------------------------------------------
//--------------------------------------
// 爆風全体の移動
//--------------------------------------
*BlastMoveAll
foreach Blast
BlastMove Blast(cnt),x,y,n
switch stat
case BLAST_FIGHT: FightDeath x,y :swbreak
case BLAST_ITEM: newmod Item,ItemClass,x,y,n :swbreak
default: :swbreak
swend
loop
return
//--------------------------------------
// 爆風全体の描画
//--------------------------------------
*BlastDrawAll
foreach Blast
BlastDraw Blast(cnt)
loop
return
//--[テロップ]------------------------------------------------------------------
//--------------------------------------
// テロップ全体の初期化
//--------------------------------------
*TelopInit
newmod Telop,TelopClass, FIGHT_CX, FIGHT_CY,COLOR_GREEN,""
newmod Telop,TelopClass, FLUSH_CX, FLUSH_CY,COLOR_GREEN,""
newmod Telop,TelopClass, SCORE_CX, SCORE_CY,COLOR_YELLOW,""
newmod Telop,TelopClass,HISCORE_CX,HISCORE_CY,COLOR_YELLOW,""
TelopRedraw=(REDRAW_FIGHT|REDRAW_FLUSH|REDRAW_SCORE|REDRAW_HISCORE)
return
//--------------------------------------
// テロップ全体の描画
//--------------------------------------
*TelopDrawAll
if(TelopRedraw){
if(TelopRedraw & REDRAW_FIGHT) :TelopSetMsg Telop(TELOP_FIGHT),strf("Left:%02d",FightLeft)
if(TelopRedraw & REDRAW_FLUSH) :TelopSetMsg Telop(TELOP_FLUSH),strf("Bomb:%02d",FightBomb)
if(TelopRedraw & REDRAW_SCORE) :TelopSetMsg Telop(TELOP_SCORE),strf("Score:%08d",Score)
if(TelopRedraw & REDRAW_HISCORE) :TelopSetMsg Telop(TELOP_HISCORE),strf("HiScore:%08d",HiScore)
if(TelopRedraw & REDRAW_ALIVE){
if(FightAlive){
newmod Telop,TelopClass,ALIVE_CX,ALIVE_CY,COLOR_WHITE,"[無敵モード]"
}
else{
delmod Telop(TELOP_ALIVE)
}
}
TelopRedraw=$0000
}
foreach Telop
TelopDraw Telop(cnt)
loop
return
//--------------------------------------
// テロップ点数の加算
//--------------------------------------
#deffunc TelopScore int _score_
Score+=_score_
if(Score>HiScore){
HiScore=Score
}
TelopRedraw|=REDRAW_SCORE
TelopRedraw|=REDRAW_HISCORE
return
//------------------------------------------------------------------------------
// End of sample43.hsp
//------------------------------------------------------------------------------
上記のサンプルの次の3つを参考にどうぞ。
*ShootingMove
*ShootingDraw
*CrashMainAll

| |
|
2016/3/9(Wed) 21:38:17|NO.74842
返信が遅れました。
申し訳ありません。
>SOU1さん
Z-indexに関わるものを特に同じ配列で管理→クイックソートですね、
現状、自分にはこれが一番適しているように思えます!
ありがとうございます。
(クイックソートの仕組み、理解できればいいなぁ)
「描画オブジェクト」は、自分には新しくてよく分からない考え方で混乱しています。
>科学太郎さん
とても参考になります!
サンプルの要素が多くてやけに凝っていますね……グラディウス的な何かかと。
モジュール型の利用法を初めて理解できたような気がします!
全く使ったことのないプログラムの形で戸惑いが大きいですが、
とても便利そうで、これはちゃんと利用できるように要練習ですね。
今の僕では、モジュール型の変数とグローバルの変数・配列変数が混同しがちで
すぐには使える自信がありません……(ツライ)
|
|
2016/3/9(Wed) 22:50:34|NO.74844
> サンプルの要素が多くてやけに凝っていますね……グラディウス的な何かかと。
HSPの学習を兼ねて懐かしいシューティング・ゲームをサンプルで作ってみました。
> モジュール型の利用法を初めて理解できたような気がします!
C++のクラスの概念がモジュール型変数なのでC++の書籍を参考にどうぞ。
> 全く使ったことのないプログラムの形で戸惑いが大きいですが、
オブジェクト指向の真似をしてるのが
#modinit
#modterm
#modfunc
#modcfunc
newmod
delmod
thismod
上記の命令、関数ですね。
> 今の僕では、モジュール型の変数とグローバルの変数・配列変数が混同しがちで
> すぐには使える自信がありません……(ツライ)
分かる気がします。
私はC/C++言語の出身でしたので難しく感じませんでした。
#module modStarClass m_x, m_y,m_c1
#deffunc StarInit
c1R=$00,$FF,$00,$FF,$00,$FF,$00,$FF
c1G=$00,$00,$FF,$FF,$00,$00,$FF,$FF
c1B=$00,$00,$00,$00,$FF,$FF,$FF,$FF
return
#modinit int _x_,int _y_,int _c1_
m_x=_x_
m_y=_y_
m_c1=_c1_
return
#modfunc StarMove
m_y++
if(m_y>=ginfo_winY):delmod thismod:return 0
return 1
#modfunc StarDraw
color c1R(m_c1),c1G(m_c1),c1B(m_c1)
circle(m_x-2),(m_y-2),(m_x+3),(m_y+3),1
return
#global
;モジュール型変数の作成
randomize
repeat 100
newmod 配列,modStarClass,rnd(640),rnd(480),rnd(8)
loop
;メイン
StarInit
repeat
redraw 0
color $CC,$CC,$CC:boxf
foreach 配列
StarMove 配列(cnt)
if(stat):StarDraw 配列(cnt)
loop
redraw 1
await(1000/60)
loop
stop
上記のモジュール型変数は次のようなメモリ構造になります。
┌────────modStarClass────────┐
│┌─配列(0) ─┐ ┌─#deffunc─┐│
││m_x m_y m_c1│←共通参照→│c1R(8) ││
│└──────┘ │c1G(8) │←StarInit命令
│┌─配列(1) ─┐ │c1B(8) ││
││m_x m_y m_c1│←共通参照→│ ││
│└──────┘ │ ││
│┌─配列(2) ─┐ │ ││
││m_x m_y m_c1│←共通参照→│ ││
│└──────┘ │ ││
│ : │ ││
│┌─配列(n) ─┐ │ ││
││m_x m_y m_c1│←共通参照→│ ││
│└──────┘ └──────┘│
└──────────────────────┘
#deffunc命令、#defcfunc関数は modStarClass 全体で共通な変数・配列となり、
#modfunc命令、#modcfunc関数は 配列要素1つ1つのメンバ変数となります。
分かりますかね?

| |
|
2016/3/10(Thu) 20:49:50|NO.74851
>科学太郎さん
モジュール変数のサンプル、丁寧な解説、ありがとうございます!
とてもわかり易いです。
module内でモジュール変数の内容・処理を定義、
newmod/dimtypeでモジュール変数or配列変数を作成、
不要になればdelmod。
モジュール変数とモジュール型変数の違いにもようやく気がつけました……。
疑問に思ったのですが、
newmodは変数の初期化処理ですが、ループ処理中に初期化を置いても重くはならないのでしょうか?
また、length(配列)を確認したところ、delmod後も要素数は変わらないようですが
delmodで何が行われているのでしょうか?
現状、delmodの意味が理解できず、newmodを使うと配列が増えるばかりなので、
modfunc等で未使用のモジュール変数を検出・初期化(初期値代入)するしか手がないように思えます。
|
|
2016/3/10(Thu) 21:02:49|NO.74852
#modfunc StarDispCheck
if(m_y>=ginfo_winY):return 0
return 1
で不使用となった変数を検出できるのではと思ったのですが、
恐らくdelmodのタイミングでエラー。
要素の削除は行われているようですし、モジュール型はlengthでは正しく取得できないのでしょうか。
また、思い切ってループ中にnewmodを置いてみたところ、
一定数以上(270くらい)には増えないことが分かりました。
コレは一体どういうことなのか、全く見当がつきません……。
|
|
2016/3/11(Fri) 23:05:31|NO.74877
> 疑問に思ったのですが、
> newmodは変数の初期化処理ですが、ループ処理中に初期化を置いても重くはならないのでしょうか?
どこのループですか?
あと newmod は変数の初期化処理ではなく変数の実態を作成します。
この実態の変数を作成するときに初期化が可能ですよ。という感じです。
> また、length(配列)を確認したところ、delmod後も要素数は変わらないようですが
> delmodで何が行われているのでしょうか?
newmod で10個の実態変数を作成すると配列の要素は10個です。
しかし、delmod で3個削除しても実態変数の要素数には変化はありません。
つまり、delmod で削除した部分が未使用領域になるだけです。
なお、この状態で newmod で実態変数を作成すると最初の未使用領域に新しい実態データが作成されます。
> 現状、delmodの意味が理解できず、newmodを使うと配列が増えるばかりなので、
はい。
増え続けると思います。
> modfunc等で未使用のモジュール変数を検出・初期化(初期値代入)するしか手がないように思えます。
newmod で新しく実態の変数を作成すると未使用領域から順番に新しい実態データがセットされますが…。
> で不使用となった変数を検出できるのではと思ったのですが、
> 恐らくdelmodのタイミングでエラー。
全ソースを載せてくれないと良く分かりませんね。
> 要素の削除は行われているようですし、モジュール型はlengthでは正しく取得できないのでしょうか。
そうですね。
newmod を10回実行して delmod を3回実行すると配列データは7個です。
しかし、内部では未使用領域が3個になってるので length では10個が返されます。
max=0
foreach 配列
max++
loop
上記のように配列の実態要素数をカウントすることは可能です。
しかし、このような使い方はモジュール型変数の便利さを損ないます。
> また、思い切ってループ中にnewmodを置いてみたところ、
どこのループかな。
> 一定数以上(270くらい)には増えないことが分かりました。
もしも、メイン・ループならば newmod、delmod を両方実行してるので
配列要素が270個に固定されたことになります。
> コレは一体どういうことなのか、全く見当がつきません……。
これは delmod で削除しても未使用領域にセットされるだけで要素数が減らないからです。
また、delmod で未使用領域があると次の newmod で最初の未使用領域が実態のある要素データになります。
分かるだろうか?

| |
|
2016/3/11(Fri) 23:35:56|NO.74878
なるほど!
newmodは、実態のない変数(未使用領域)がなければ、変数を初期化する
delmodは、実態のない変数へ置き換える("変数"を削除する訳ではない)
lengthは、実態の有無に関わらず要素数をそのまま帰す
foreachやvaruse()は、実態の有無を確認できる
ということだったのですね。
しかも、僕は「delmodが変数を丸ごと消し去るもの」だと勘違いしていたと……
|
|
2016/3/11(Fri) 23:41:07|NO.74879
> newmodは、実態のない変数(未使用領域)がなければ、変数を初期化する
正確には未使用領域が無ければ実態変数(要素数)を1つ追加します。
(追加と共に初期化もするが…)
> delmodは、実態のない変数へ置き換える("変数"を削除する訳ではない)
デバッグ画面で確認できると思います。
未使用領域を意味する表示がされてるはずです。
> lengthは、実態の有無に関わらず要素数をそのまま帰す
はい。
> foreachやvaruse()は、実態の有無を確認できる
> ということだったのですね。
はい。
> しかも、僕は「delmodが変数を丸ごと消し去るもの」だと勘違いしていたと……
名前からするとそうですね。
でも、モジュール型変数は特別な動作をするようです。
特に foreach が要素数ではなく実態のある要素数しか繰り返しませんので。
|
|
2016/3/12(Sat) 00:23:15|NO.74882
newmodとdelmod、モジュール変数の状態が、やっと、理解できました!
スッキリした……
>> 全く使ったことのないプログラムの形で戸惑いが大きいですが、
>オブジェクト指向の真似をしてるのが...
HSPとプチコンBASICを少し触れる程度の知識しか無いのでよく分からなかったのですが、
ひょっとして、
モジュール変数を定義するもの(module,modinit,modfunc,modcfuncなど)をクラス、
モジュール型変数をオブジェクトと呼ばれるものなのでしょうか?
オブジェクト指向がどうのこうのと言うcもjavaもよく分からない……
そしてhspもオブジェクト指向をぶっこんでくるのか……
ああ、頭痛が激痛で痛くなりそう
|
|
2016/3/13(Sun) 11:23:42|NO.74896
> モジュール変数を定義するもの(module,modinit,modfunc,modcfuncなど)をクラス、
> モジュール型変数をオブジェクトと呼ばれるものなのでしょうか?
はい。
そうですね。
ゲームならば「オブジェクト」=「自機」=「敵機」=「ミサイル」=「アイテム」などになるでしょう。
> オブジェクト指向がどうのこうのと言うcもjavaもよく分からない……
オブジェクトという言葉を部品とか、パーツなどと解釈すると分かりやすいです。
TamaF(100)、TamaX(100)、TamaY(100)などと配列で100個の弾丸パーツを管理する方法から
modTamaClassでTama(0)~Tama(99)を管理して1つの配列要素内に m_x、m_y を持つ。
つまり、弾丸パーツのすべての変数を1つの配列要素内で一丸管理できるわけです。
C言語の構造体のイメージです。
この構造体に処理する命令、関数を付けたのがC++言語のクラス概念。
そのC++言語の真似が(module,modinit,modfunc,modcfuncなど)ですね。
> そしてhspもオブジェクト指向をぶっこんでくるのか……
上級者向けという位置づけでしょう。
> ああ、頭痛が激痛で痛くなりそう
まぁ。
気軽にサンプルでも作って行けば良いでしょう。
|
|
2016/3/13(Sun) 13:05:14|NO.74898
構造体とクラスはほとんど同じ意味だったんですね。
スレの本題に「全てのオブジェクトの描画順を自由にできるようにしたい」がありますが、
オブジェクト指向で作っていくとあると、
描画処理以外をBulletMove、BulletHitCheck()のように処理していくとして
描画処理はどのように組んでいけばいいのでしょうか…
z-indexを……でもクラスは別個だし、global変数でz-indexを……でもmoduleとglobalの紐付け……???
思い浮かばない。
ソートに関しては、サンプルソースを漁ってみたところ
hspのrnd()1000個の要素に対してのソートならマージソートが最速だと認識しています。
|
|
2016/3/13(Sun) 16:16:02|NO.74899
> スレの本題に「全てのオブジェクトの描画順を自由にできるようにしたい」がありますが、
ここが良く分からないのです。
一般的な描画は
背景
↓
自機弾
↓
自機
↓
敵弾
↓
敵機
↓
爆風
↓
アイテム
↓
テロップ(スコアなど)
↓
最上位メッセージ(Warrningなど)
上記のように自機弾グループ、自機グループ、爆風グループという感じで一括で描画するはずです。
> 描画処理はどのように組んでいけばいいのでしょうか…
どのような描画を望んでるのでしょうか?
ここが知りたいです。
> 敵・味方・設置物・エフェクト・地形・背景(層有り)・弾丸など
> 全てのモノが関連して描画順を自由に変えられるようにしたいのですが、
> 何が何だか全く分からない状態なので、皆さんの意見を参考にさせて頂けませんか?
関連して描画順を変える必要性が良く分かりませんね。
どんなゲーム・システムですか?
> z-indexを……でもクラスは別個だし、global変数でz-indexを……でもmoduleとglobalの紐付け……???
とりあえず、描画順とオブジェクトを紐づけた独自のスプライト・クラスを用意すれば良いが…。
このモジュール・クラスは敵・味方・設置物・エフェクト・地形・背景(層有り)・弾丸などを
種類IDとして、オブジェクトID(配列の添え字番号)、ZオーダーID(描画順)の3つを管理しており、
Zオーダー順に双方向リストでオブジェクトを鎖のように登録します。
描画時はZオーダー順の複数の双方向リストのチェーン・データを順番に描画します。
つまり、複数のZオーダー順の双方向リスト・チェーンを二分木処理で登録します。
これならばソートするよりも高速にZオーダー順にオブジェクトをチェーン登録可能。
┌───────────modSpriteClass───────────┐
│┌─┐ ┌──────┐┌──┐ │
││オ├→│描画レベル99├┤OBJ1│ │テロップ
││ブ│ └──────┘└──┘ │
││ジ│ : │
││ェ│ ┌──────┐┌──┐┌──┐ │
登録││ク├→│描画レベル03├┤OBJ1├┤OBJ2│ │自機
┌─→│ト│ └──────┘└──┘└──┘ │
│ ││の│ ┌──────┐┌──┐ │
│ ││二├→│描画レベル02├┤OBJ1│ │自機弾
│ ││分│ └──────┘└──┘ │
│ ││木│ ┌──────┐┌──┐┌──┐┌──┐┌──┐ │
│ ││ ├→│描画レベル01├┤OBJ1├┤OBJ2├┤OBJ3├┤OBJ4│ │背景
│ │└─┘ └──────┘└──┘└──┘└──┘└──┘ │
│ └─────────────────────────────┘
ZオーダーID(描画レベル01~描画レベル99)
種類ID(敵・味方・設置物・エフェクト・地形・背景(層有り)・弾丸など)
オブジェクトID(オブジェクト・クラスの配列添字番号)
・二分木
https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%9C%A8
・二分探索木
https://ja.wikipedia.org/wiki/%E4%BA%8C%E5%88%86%E6%8E%A2%E7%B4%A2%E6%9C%A8
・ヒープソート
https://ja.wikipedia.org/wiki/%E3%83%92%E3%83%BC%E3%83%97%E3%82%BD%E3%83%BC%E3%83%88
・連結リスト(双方向リスト)
https://ja.wikipedia.org/wiki/%E9%80%A3%E7%B5%90%E3%83%AA%E3%82%B9%E3%83%88

| |
|
2016/3/13(Sun) 22:29:46|NO.74907
なるほど、そのように考えればいいんですね。
ヒープソート・連結リストの考え方が分からないので完全に理解するまで時間がかかりそうで、
すぐには実装できそうにありません。
>どのような描画を望んでるのでしょうか?...
>関連して描画順を変える必要性が良く分かりませんね。
>どんなゲーム・システムですか?
2Dゲーム、特に縦スクロールSTGです。
例えてしまえば、レイフォースのような奥行きのあるギミックが多めの2Dゲームです。
敵や雲、地形、敵弾などが上下(Z軸)に動くことがあり、
明らかに、自機より下に位置するキャラクター・自機よりも上に位置するキャラクターの
描画順が操作できないと不便なのです。
地形(背景スクロール)と一口に言っても、自機よりも下方にある地面や
自機と地面の中間層にある雲。その雲の下から上に登ってくる敵やミサイルなど。
|
|
2016/3/13(Sun) 23:10:05|NO.74908
> 2Dゲーム、特に縦スクロールSTGです。
> 例えてしまえば、レイフォースのような奥行きのあるギミックが多めの2Dゲームです。
このゲームは知らないが…。
> 地形(背景スクロール)と一口に言っても、自機よりも下方にある地面や
> 自機と地面の中間層にある雲。その雲の下から上に登ってくる敵やミサイルなど。
なるほど。
面白そうなシューティングですね。
うーん。
オブジェクト・クラス、その管理、描画スプライト・クラスを
じっくり考えないとモジュール型変数にした段階で破綻しそうですね。
ちょっとゲーム・キャラクタの仕様が欲しいですね。
この掲示板か、自身のホームページあたりに、まとめてみてはどう?
今後、色々と質問するにあたり便利でしょうから。
|
|
2016/3/13(Sun) 23:25:50|NO.74910
|
|
2016/3/13(Sun) 23:41:07|NO.74911
>> 例えてしまえば、レイフォースのような奥行きのあるギミックが多めの2Dゲームです。
>このゲームは知らないが…。
レイフォース面白いですよ。音楽もギミックも景観も演出も最高。
自機よりも下方の敵への攻撃手段があって面白いんです。
僕自身詳しくないですが90年台のゲームらしいです。
似たような雰囲気のゲームに同人ゲームの神威ってのもありますよ。
>ちょっとゲーム・キャラクタの仕様が欲しいですね。
オブジェクト指向を知る前に組んだプログラムで全て配列で管理していますが、
そもそも右も左も分からず、高1の時のお馬鹿な自分がテキトーに書きだしたプログラムで、
だいぶスパゲティ化が進んでいますが……
分かりました。
できるだけ細く描写・オブジェクト関係を書き出してみます。
(俺の作業ペースくそ遅いけど、0時半までにはまとめられるかな)
|
|
2016/3/14(Mon) 00:35:07|NO.74912
|
|
2016/3/14(Mon) 19:49:22|NO.74919
どうも上手く理解できませんでした。
>描画時はZオーダー順の複数の双方向リストのチェーン・データを順番に描画します。
双方向リスト?というもの自体初耳でした。
自分なりに解釈しましたが、今回の場合は、
スプライトクラス内で
dim chainlist,スプライト数,{2(次の添字,前の添字) +3(Zオーダー,種類ID,オブジェクトの添字)}
のように定義して、
ん?次の要素前の要素へのリンクはどうやって決めるんだろう
データ(Zオーダー,種類ID,オブジェクトの添字)を先に代入して、
あとから何かしらの手段でリンク(次の添字,前の添字)を貼っていく?
それっぽい
でも"何かしらの手段"が分からない……
>つまり、複数のZオーダー順の双方向リスト・チェーンを二分木処理で登録します。
>これならばソートするよりも高速にZオーダー順にオブジェクトをチェーン登録可能。
「Zオーダー順の双方向リストに二分木処理で登録」が意味するものが全く……
二分木処理とは、ヒープソートのことですか?
ヒープソートも、その前段階の二分ヒープも、
なんとなくのイメージはあるのですが、図のノードの繋がりが変数・プログラムで
どう表わされるのかさえ分かりませんでした。
こうなったら、サンプルソースを流用して「二分木処理?」をどうにかするしか……
>これならばソートするよりも高速にZオーダー順にオブジェクトをチェーン登録可能。
ソートは利用していない
あれ?
二分木処理っていったい???
|
|
2016/3/14(Mon) 21:33:51|NO.74920
> 僕自身詳しくないですが90年台のゲームらしいです。
こちらが高校生をやってた時代ですか。
> 似たような雰囲気のゲームに同人ゲームの神威ってのもありますよ。
こちらは知ってます。
20歳代のゲーム制作にハマってた時期に遊びました。
100円ショップのダイソー・ゲームで宣伝してましたね。
> できるだけ細く描写・オブジェクト関係を書き出してみます。
お待ちしてます。
> (俺の作業ペースくそ遅いけど、0時半までにはまとめられるかな)
1週間以内なら良いのでマイ・ペースでどうぞ。
> どうも上手く理解できませんでした。
サンプルを作成して載せた方が早いかもしれない。
でも、その前にそれぞれの仕様(企画)を知りたいですね。
> 主要な変数と描画順をまとめてみました。
変数の仕様よりもキャラクタなどのオブジェクトの仕様が欲しいですね。
背景レイヤー
ギミック・レイヤー(1)
雲レイヤー
ギミック・レイヤー(2)…自機
鉄筋レイヤー
ギミック・レイヤー(3)
エフェクト・レイヤー(爆発や閃光,火花など)
レイヤーの仕様は上記の様ですか?
|
|
2016/3/14(Mon) 22:27:54|NO.74921
>100円ショップのダイソー・ゲームで宣伝してましたね。
はぇ、ダイソーで。
現状、描画方法(レイヤー構成)は科学太郎さんの言うところの「一般的な描画」と
全く同じです。
背景
↓
自機弾
↓
自機
↓
敵弾
↓
敵機
↓
爆風
↓
アイテム
↓
テロップ(スコアなど)
↓
最上位メッセージ(Warrningなど)
>レイヤーの仕様は上記の様ですか?
ほぼその通りです。
>でも、その前にそれぞれの仕様(企画)を知りたいですね。
仕様というと、理想の描画ルーチンの形・どのような描写を行いたいか でしょうか。
|
|
2016/3/14(Mon) 23:22:23|NO.74922
> 仕様というと、理想の描画ルーチンの形・どのような描写を行いたいか でしょうか。
はい。その通りです。
|
|
2016/3/15(Tue) 15:13:21|NO.74924
現在は配列で全て管理していますが、ゆっくりとモジュール型変数へ移行していくと思います。
理想の描画ルーチンの形……実はあまり具体的なイメージがありません。
僕のやりたい「全てのオブジェクトの描画順は自由に変えられる」というのを
ものにするために、どのような形であればいいのか分からないからです。
まあ、思いつく限りで書いてみます。
■ルーチン
...諸処理...
↓
描画処理(どうしていいか分からない)
・アニメーションなど
行動ルーチンに関係のない描画固有の処理とか
・z-index、ソート?紐付け?
・描画
ものすごく普通……?
■どんな描写を行うか
・大分類
キャラクター(自機・敵・障害物・アイテム("無害で有益な敵"みたいな扱い))
地形と背景(多層。自機の上に半透明で描写したり)
エフェクト
+
最前面にUI(テロップやゲージなど)
・エフェクト
水しぶき・火花・爆炎・アフターバーナ(ノズル噴射など)・
鉄片・雷(部分発光)・煙(巻き上げられた雲やミサイルの尾など)・土埃は
全てまとめてエフェクトとして処理したほうが楽そう。
爆死アニメーションについては、
最小型の敵キャラ以外は死亡時も単爆発ではない演出が入りますので、
死亡時の爆発はキャラクターオブジェクトとは別に、
エフェクトオブジェクトを使って描画したいかも?
というかそれが一般的?
・地形と背景
地形,背景(ループスクロール)の違いです。
「地形なんてどうやって描写していいか分からねぇ!」
「とりあえずループだ!」
「シーン替えは二枚のタイルを利用して上手く繋げよう!」
というものすごいテキトーなノリでループスクロールを作ってみたのですが
残念なことにそこそこ上手いこと良い演出をしてしまって、
ループスクロールを外せません。
かと言って"当たり判定のある複雑な地形"を外してしまうと演出上の問題が。
というわけで
地形と背景…というより地形とループ地形を共存させたいと思います。
あれ、これも一般的な気がする。
一応多関節のキャラクターも視野に入れています。
現在、複数部位の敵を、
パーツごとに一つのキャラクターとして扱い、
objren()に親の配列変数の添字を代入しておいてリンクさせている状況です。
多関節の仕組みや描写方法は、考え中です。(未来永劫思いつかないと思う)
|
|
2016/3/17(Thu) 14:32:39|NO.74931
>オブジェクト指向を知る前に組んだプログラムで全て配列で管理していますが、
>そもそも右も左も分からず、高1の時のお馬鹿な自分がテキトーに書きだしたプログラムで、
>だいぶスパゲティ化が進んでいますが……
この気持ちがよくわかります^^;
昔、私も全て配列で管理していました。
その時はオブジェクトをうまく並列に動作させるように
プログラムするのに苦労した記憶があります
私はオブジェクト指向をすべて知った訳ではありませんが
比較的小規模はプログラムなら
配列で管理しても問題ないような気がします。
肝心なのは後から見てもわかるようなプログラムですね。
スパゲティにならないようにするには
ともかくコメントとか解説をたくさん書くことですね
それこそプログラムよりコメントとか解説が多いぐらいに(^^;
キー入力も配列変数に格納して後で見たようが見やすかったです。
役に立つかわかりませんが自己流ですが並列動作のサンプルを書いてみました
;-------------------------------------------------
;
; 並列動作 サンプル
;
;-------------------------------------------------
; このスプリクトはオブジェクト用配列を使って
; 各オブジェクトを並列に動作するようにプログラムしています
; 各オブジェクトはイベント配列の内容に従って動作します
;
; イベント配列は数値をテーブル化して表しています
; 見やすくなるように#defineで定義しています
;-------------------------------------------------
;
; イベント配列
;
; event_tblという配列テーブルを使う
; event_tbl p1,p2,,,,
; p1 は確定でイベント番号が入る
; p2 は確定で待ちフレームが入る
; p2以降はイベント番号によって変わる
; 今回は 5個 確保していますが
; 規模が大きくなると増えます
;-------------------------------------------------
;-------------------------------------------------
;
; オブジェクト配列
;
; obj_tbl p1,p2,p3,p4,p5
; p1 状態 0以外だと オブジェクトがイベント実行中
; p2 イベント番号
; p3 イベントカウント
; p4 X座標
; p5 Y座標
; 今回は 5個 確保していますが
; 規模が大きくなると増えます
;-------------------------------------------------
dim event_tbl,5,100
dim obj_tbl,5,100
;-------------------------------------------------
;
; 各イベント解説
;
;-------------------------------------------------
; イベント1番 子obj出現
;
; 解説
; フレーム待ち後現在のobjとは別にobjを出現させる
; イベント番号と現在のobjとの座標差分を指定する
;
; EVENT_OBJ p1,p2,p3,p4
; p1 待ちフレーム
; p2 親objとのx座標差分
; p3 親objとのy座標差分
; p4 イベントno
;-------------------------------------------------
;-------------------------------------------------
; イベント2番 objの移動処理
;
; 解説
; objのx座標y座標を待ちフレーム後加算する
;
; EVENT_POSMOVE p1,p2,p3
; p1 待ちフレーム
; p2 x座標差分
; p3 y座標差分
;-------------------------------------------------
;-------------------------------------------------
; イベント3番 待ちフレーム
;
; 解説
; 待ちフレームのみでなにもしない
; 待ったあと次のイベントに進む
;
; EVENT_NOP p1
; p1 待ちフレーム
;-------------------------------------------------
;-------------------------------------------------
; イベント4番 終了
; 解説
; 待ちフレーム後オブジェクトを消去する
;
; EVENT_END p1
; p1 待ちフレーム
;-------------------------------------------------
;-------------------------------------------------
; イベント5番 ループ
; 解説
; 待ちフレーム後 指定回数分戻る
;
; EVENT_LOOP p1,p2,p3
; p1 待ちフレーム
; p2 ループ回数
; p3 戻る数
;-------------------------------------------------
;
; 注意 待ちフレームが0の場合は
; 待たずに次のイベントに行く
;-------------------------------------------------
; event_adr++の意味
;
; イベントを定義したあと1を加算して
; 次のイベントの準備
;-------------------------------------------------
#define EVENT_OBJ(%1=0,%2=0,%3=0,%4=0,%5=0) event_tbl(0,event_adr) = 1,%1,%2,%3,%4 : event_adr++
#define EVENT_POSMOVE(%1=1,%2=0,%3=0) event_tbl(0,event_adr) = 2,%1,%2,%3 : event_adr++
#define EVENT_NOP(%1=0) event_tbl(0,event_adr) = 3,%1 : event_adr++
#define EVENT_END(%1=0) event_tbl(0,event_adr) = 4,%1 : event_adr++
#define EVENT_LOOP(%1=0,%2=0,%3=0) event_tbl(0,event_adr) = 5,%1,%2,%3 : event_adr++
;-------------------------------------------------
; イベント用の番号セット
; ラベルのような感じで使いますが変数のため数字しか使えません
; EVENT_NO_SET
;-------------------------------------------------
#define EVENT_NO_SET(%1=0) event_tbl_no(%1) = event_adr
dim event_tbl_no,100
dim loop_tbl,100
;-------------------------------------------------
; ラベル型変数の定義
;-------------------------------------------------
ldim lavel,20
lavel(1)=*lavel_OBJ
lavel(2)=*lavel_POSMOVE
lavel(3)=*lavel_NOP
lavel(4)=*lavel_END
lavel(5)=*lavel_LOOP
;-------------------------------------------------------------------------------
;
; イベントデータ
;
;-------------------------------------------------------------------------------
event_adr=0 ; イベントアドレスクリア
;-------------------------------------------------------------------------------
; 親objイベント(マスター)
;-------------------------------------------------------------------------------
EVENT_NO_SET 0 ;イベント番号0
EVENT_POSMOVE 1,100,450 ;親obj移動 1フレーム待ち後x座標100,y座標を450足す
repeat 10 ;通常のループ 10回あるので 配列を余分に使ってしまう
EVENT_OBJ 0,0,0,1 ;子obj出現 イベント番号1をセット
EVENT_POSMOVE 1,4,0 ;親obj移動 1フレーム待ち後x座標を4足す
EVENT_LOOP 0,10,1 ;ループ処理 待ちフレームなしで10回イベントをひとつ戻す
;増える配列がひとつなので効率がいいが今は2重ループができない
loop
EVENT_OBJ 0,0,0,1 ;子obj出現 イベント番号1をセット
EVENT_END 10000 ;10000フレーム後終了
;-------------------------------------------------------------------------------
; 子obj用イベント
;-------------------------------------------------------------------------------
EVENT_NO_SET 1 ;イベント番号1
EVENT_POSMOVE 1,0,-2 ;子obj移動 1フレーム待ち後y座標を2引く
EVENT_LOOP 0,50,1 ;ループ処理 待ちフレームなしで50回イベントをひとつ戻す
EVENT_OBJ 0,0,0,2 ;孫obj出現 イベント番号2をセット
EVENT_POSMOVE 1,0,-2 ;子obj移動 1フレーム待ち後y座標を2引く
EVENT_LOOP 0,150,1 ;ループ処理 待ちフレームなしで150回イベントをひとつ戻す
EVENT_END ;待ちフレームなし終了
;-------------------------------------------------------------------------------
; 孫obj用イベント
;-------------------------------------------------------------------------------
EVENT_NO_SET 2 ;イベント番号2
EVENT_POSMOVE 1,1,-5 ;孫obj移動 1フレーム待ち後x座標を1足しy座標を5引く
EVENT_LOOP 0,20,1 ;ループ処理 待ちフレームなしで20回イベントをひとつ戻す
EVENT_POSMOVE 1,0,-5 ;孫obj移動 1フレーム待ち後y座標を5引く
EVENT_LOOP 0,20,1 ;ループ処理 待ちフレームなしで20回イベントをひとつ戻す
EVENT_END ;待ちフレームなし終了
;-------------------------------------------------------------------------------
;
; メインループ
;-------------------------------------------------------------------------------
obj_tbl(0,0)=1,0,0,-10,-10 ; 親obj(マスター)をイベント番号0で出現させる
;x座標-10 y座標-10 イベント番号0
repeat 10000
;-------------------------------------------------------------------------------
; イベント処理
;-------------------------------------------------------------------------------
*event_main
repeat 100
obj_num=cnt
if (obj_tbl(0,obj_num) >= 1){ ;obj_tbl(0 状態 0(非表示) 1(表示)
*event_main_a
event_num=obj_tbl(1,obj_num);obj_tbl(1 イベント番号
if (event_tbl(1,event_num) <= obj_tbl(2,obj_num)){ ;obj_tbl(2 イベントカウント
;イベントカウント以下だったらイベントを実行する
gosub lavel(event_tbl(0,event_num))
if obj_tbl(0,obj_num)=0 : continue
obj_tbl(1,obj_num)++;次のイベント
obj_tbl(2,obj_num)=0;イベントカウント初期化
goto *event_main_a
}
obj_tbl(2,obj_num)++;イベントカウント更新
}
loop
;-------------------------------------------------------------------------------
; オブジェクト表示処理
;-------------------------------------------------------------------------------
color 0,0,0
repeat 100
if (obj_tbl(0,cnt) >= 1){ ;実行中を探す
x=obj_tbl(3,cnt)
y=obj_tbl(4,cnt)
boxf x,y,x+10,y+10
}
loop
await 17
loop
end
;-------------------------------------------------------------------------------
;
; 以下イベントプログラム
;
;-------------------------------------------------------------------------------
*lavel_OBJ;EVENT_OBJ 1番
x=obj_tbl(3,obj_num)
y=obj_tbl(4,obj_num)
repeat 100
if obj_tbl(0,cnt)=0{ ;空きを探す
obj_tbl(0,cnt)=1 ;状態セット
obj_tbl(1,cnt)=event_tbl_no(event_tbl(4,event_num));イベントセット
obj_tbl(2,obj_num)=0 ;イベントカウント初期化
obj_tbl(3,cnt)=x+event_tbl(2,event_num) ;X座標セット
obj_tbl(4,cnt)=y+event_tbl(3,event_num) ;Y座標セット
break
}
loop
return
;-------------------------------------------------------------------------------
*lavel_POSMOVE ;EVENT_POSMOVE 2番
obj_tbl(3,obj_num)+=event_tbl(2,event_num) ;X座標加算
obj_tbl(4,obj_num)+=event_tbl(3,event_num) ;Y座標加算
return
;-------------------------------------------------------------------------------
*lavel_NOP ;EVENT_NOP 3番
return
;-------------------------------------------------------------------------------
*lavel_END ;EVENT_END 4番
obj_tbl(0,obj_num)=0 ;状態クリア
return
;-------------------------------------------------------------------------------
*lavel_LOOP ;EVENT_LOOP 5番
loop_tbl(obj_num)++
if event_tbl(2,event_num) < loop_tbl(obj_num) {;通常
loop_tbl(obj_num)=0;ループカウンターリセット
}else{
obj_tbl(1,obj_num)-=event_tbl(3,event_num)+1;戻り
}
return

| |
|
2016/3/17(Thu) 18:05:49|NO.74933
> まあ、思いつく限りで書いてみます。
どうやら描画の問題よりもオブジェクトの管理を考えた方が良いかもしれない。
1つのオブジェクト(キャラクタ)に全ての機能を持たせるわけです。
そうすればオブジェクトの描画は「オブジェクトの持つZオーダー順」に描画すれば良いので
いくらでも描画順を変えられることになります。
よって1つのオブジェクトは、
アニメ処理の有無(パラメータ多数)
あたり判定の有無(パラメータ多数)
移動カウンタ
移動テーブル
> 一応多関節のキャラクターも視野に入れています。
これに対応するには、1つのオブジェクトに子供のオブジェクトを双方向リストの考えで
鎖のようにチェーンで結ばれてるように管理するわけです。
描画時は末尾の尻尾キャラクタから描画して、先頭の頭部キャラクタを描画。
これで蛇キャラクタからロボットのような多関節キャラクタまで対応が聞くと思います。
> パーツごとに一つのキャラクターとして扱い、
親パーツに手足などの関節キャラを結び付けた方が良いでしょう。
> objren()に親の配列変数の添字を代入しておいてリンクさせている状況です。
親のみか?
1つのオブジェクトに自機・敵機・自機弾・敵機弾・障害物・アイテム・エフェクト効果など
万能キャラクタを用意すれば描画順は任意のタイミングでZオーダーを変えたら
次の描画タイミングで直ぐに反映するようになりますね。
> 多関節の仕組みや描写方法は、考え中です。(未来永劫思いつかないと思う)
これも考慮に入れて1つのオブジェクト管理を設計しないとまずいかもね。
配列方式でも1つのオブジェクトで全てのキャラクタを表現できるようにすれば良いので。
モジュール型変数か、配列方式かは2の次な気がしてきました。
配列タイプでも良いので動く実行ファイルなどを公開して欲しいですね。
その動きからデータ構造を新たに考えた方がよさそうです。
一通り配列タイプで完成させてみるのはどうですか?
その次のバージョン・アップでモジュール型変数に対応するとか。
|
|
2016/3/17(Thu) 22:10:02|NO.74934
>kさん
すごい、何がすごいのかよく分からないけれど何かすごい。
ラベル変数も使い方がよく分からなかったのですが、
動作パターンをそのように組み立てることができるんですね。
イベント管理・並列処理、とても参考になります。
パッと見ただけでは、見たことがない型だからなのかすぐには理解できそうにありません。
またしても見たことがない作り……勉強不足すぎ。
スタック…じゃない、キュー?の構造になっているのでしょうか……
>科学太郎さん
この記事にツイッターにupされた動画が埋め込まれているので、参考になれば。
もしかすると限定配布なら許してもらえるかも……
http://d.hatena.ne.jp/st1105/20160202/1454428004
>どうやら描画の問題よりもオブジェクトの管理を考えた方が良いかもしれない。
>1つのオブジェクト(キャラクタ)に全ての機能を持たせるわけです。
やはり、グダグダなシステムでボロが出まくっていますし、
そもそも足りていない機能がありまくり。
考えなおしですよね……
>> 一応多関節のキャラクターも視野に入れています。
>これに対応するには、1つのオブジェクトに子供のオブジェクトを双方向リストの考えで
双方向リストは確か、"次"と"前"の配列添え字を保持しておくものでしたっけ。
それでいて次か前にしかアクセス出来なかった気がするので、
親objへダメージを伝えたりするためにするには、既存のobjrenを
objren num,3
0:親へのリンク(0なら単体)
1:前(-1なら最初)
2:次(-1なら最後)
のようにすれば双方向リストとしても成り立ちますよね。
>一通り配列タイプで完成させてみるのはどうですか?
モジュール型に不慣れな現状で、あれができないこれができない、なんて問題が出る度に
ここに質問しに来たり、サンプルを組んでみたりするのでは時間がかかってしょうがありません。
そうですね、配列タイプで完成させます。
モジュール型は次回作でトライします。
多関節で思い出しましたが、
一つのオブジェクトに複数の当たり判定を持たせる場合
どこに当たり判定(矩形)の相対座標(親との座標差分)を代入すればいいのか悩んでいます。
objat(キャラ数,当たり判定64個くらい確保,2(xy相対座標))
なんて初期化した日には、
当たり判定が矩形一個のキャラなら63*2個の変数(確保されたメモリ?)が無駄になると思うのです。
複数の矩形当たり判定をどこに置いておけば良いのか、分かりません。
ただの配列では無いんでしょうけど

| |
|
2016/3/17(Thu) 23:16:46|NO.74937
>多関節で思い出しましたが、
>一つのオブジェクトに複数の当たり判定を持たせる場合
>どこに当たり判定(矩形)の相対座標(親との座標差分)を代入すればいいのか悩んでいます。
その辺は
グラディウスⅡ グラディウスⅢ 当たり判定などで
動画を検索するといくつか出てきますが
いろいろですね^^;
|
|