--[[ オブジェクトの当たり判定機能のサンプル ]] function Initialize() SetWorldSize(1024, 1024) SetViewSize(480, 272) SetViewPos(0, 0) SetDrawSize(480, 272) SetDrawPos(0, 0) -- 描画システムの初期化 GraphicInitialize( 1, -- SCREEN_MODE_REALSIZE (0) -- PCとPSPの区別をつけず、座標とサイズをそのまま適用 -- SCREEN_MODE_FIT_PSP (1) -- PSPを基準にしてPCでは座標系を倍のサイズとして処理をする -- SCREEN_MODE_FIT_PC (2) -- PCを基準にしてPSPでは座標系を半分のサイズとして処理をする 0, -- テクスチャデータの扱いかた -- TEXTURE_MODE_REALSIZE (0) -- テクスチャをPSPでもそのまま読み込む -- TEXTURE_MODE_SHRINK (1) -- テクスチャをPSPでは半分のサイズにして読み込む 11, -- 64サイズのテクスチャ使用枚数 0, -- 128サイズのテクスチャ使用枚数 2, -- 256サイズのテクスチャ使用枚数 0, -- 512サイズのテクスチャ使用枚数 0, -- 1024サイズのテクスチャ使用枚数 1, -- フォントの使用種類数 1) -- アニメデータの使用数 alice = LoadGraphic("ladder.bmp") block = LoadGraphic("block/normal/box.bmp") font = LoadFontSprite("test") -- 描画先 DRAW_TO_WORLD = 0 DRAW_TO_VIEW = 1 DRAW_TO_SCREEN = 2 -- ボタンの状態 BUTTON_STATUS_NO = (-1) -- 押していない BUTTON_STATUS_PUSH = (0) -- 押した瞬間 BUTTON_STATUS_HOLD = (1) -- 押している BUTTON_STATUS_PULL = (2) -- 離した瞬間 -- ボタン番号 BUTTON_NUMBER_NONE =0 BUTTON_NUMBER_L1 =1 BUTTON_NUMBER_L2 =2 BUTTON_NUMBER_R1 =3 BUTTON_NUMBER_R2 =4 BUTTON_NUMBER_SELECT =5 BUTTON_NUMBER_START =6 BUTTON_NUMBER_TRIANGLE =7 BUTTON_NUMBER_SQUARE =8 BUTTON_NUMBER_CROSS =9 BUTTON_NUMBER_CIRCLE =10 BUTTON_NUMBER_UP =11 BUTTON_NUMBER_DOWN =12 BUTTON_NUMBER_RIGHT =13 BUTTON_NUMBER_LEFT =14 BUTTON_NUMBER_MAX =15 Anime = CreateAnimation("AnimeAliceWalkRight") time = 20 SetAnimationData(Anime, alice, 0, 128, 64, 64, -16, 0, time); SetAnimationData(Anime, alice, 64, 128, 64, 64, -16, 0, time); SetAnimationData(Anime, alice, 0, 128, 64, 64, -16, 0, time); SetAnimationData(Anime, alice, 128, 128, 64, 64, -16, 0, time); -- オブジェクトシステム初期化 -- オブジェクト登録可能最大数を設定 -- -- ObjectDataInitialize(MoveObjectNumber, BoxNumber, TriangleNumber, BackBlockNumber) -- 引数 -- MoveObjectNumber -- 移動するキャラクターなどの数を指定します -- 今回はこの部分だけのサンプルです -- -- BoxNumber -- TriangleNumber -- 障害物などブロックの数を指定します -- オブジェクトは速度を与えると -- 自動でブロックとの衝突判定を行いつつ移動します -- -- BackBlockNumber -- ブロックとは別に画像表示用のキャラクター数 -- -- 登場させるオブジェクトの数 MaxObjectNumber = 11 -- オブジェクトを初期化 ObjectDataInitialize(MaxObjectNumber, 0, 0, 0) -- オブジェクトの情報を初期化 -- オブジェクト番号1はプレイヤー 2からあとは障害物 obj = {} for i=1, MaxObjectNumber-1, 1 do obj[i] = {} end -- プレイヤーの情報を初期化 player = {} player.no = 1 player.motion = Anime player.pattern = 1 player.count = 0 SetObjectSize(player.no, 32, 63) -- オブジェクトを有効にする -- SetObjectUse(id, status) -- 引数 -- id -- 対象のオブジェクト番号 -- status -- オブジェクトの有効無効を設定 -- 1:有効 -- 0:無効 -- SetObjectUse(player.no, 1) -- 有効無効を知りたいときは -- status = SetObjectUse(id) -- オブジェクト同時の衝突判定の対象とするを設定 -- SetObjectHitCheck(id, value) -- 引数 -- id -- 対象となるオブジェクトの番号 -- value -- 1 判定対象とする -- 0 判定対象としない -- SetObjectHitCheck(player.no, 1) -- オブジェクト同士の衝突判定の対象となっているか調べる -- value = GetObjectHitCheck(id) -- 引数 -- id -- 対象のオブジェクト番号 -- 戻り値 -- 1 判定対象となっている -- 0 判定対象となっていない -- -- 当たり判定のグループ設定 -- オブジェクトをグループとしてまとめておくことができる -- 当たり判定を行うときにグループを指定して判定を行うことができる -- -- 例えば、自キャラ、敵弾、敵などと同じグループで分けたとして -- 「自キャラ×敵弾、自キャラ×敵」で判定を行える -- 「敵キャラ×敵弾」の判定処理を無駄に行わずにすむ、はず -- SetObjectGroupID(id, group) -- 引数 -- id -- 対象となるオブジェクト番号 -- group -- 与えるグループ番号 -- SetObjectGroupID(player.no, 1) -- 自キャラにグループ番号1番を与えている -- 当たり判定のグループ番号を取得する -- group = GetObjectGroupID(id) -- 引数 -- id -- 対象となるオブジェクト番号 -- 戻り値 -- group -- グループ番号 -- スコア管理の変数 score = 0 high_score = 0 -- 初期化 InitializeGame() return end --[[ ゲームの初期化 ]] function InitializeGame() -- プレイヤーを初期は位置に戻して速度も0へ SetObjectPosition(player.no, 0, 272/2) SetObjectVelocityReal(player.no, 0, 0) ObjectDataClearMoveLeft(player.no) score = 0 for i=1, MaxObjectNumber-1, 1 do InitializeObject(i, i+1) end return end --[[ オブジェクトの情報を初期化する ]] function InitializeObject(no, id) -- オブジェクトの設定 obj[no].no = id SetObjectSize(obj[no].no, 16, 16) SetObjectPosition(obj[no].no, math.random(350, 450), math.random(0, 250)) SetObjectVelocityReal(obj[no].no, math.random(-300, 300), math.random(-300, 300)) ObjectDataClearMoveLeft(obj[no].no) SetObjectUse(obj[no].no, 1) SetObjectHitCheck(obj[no].no, 1) -- 敵(ブロック)の当たり判定は2番のグループとする BLOCK_GROUP = 2 SetObjectGroupID(obj[no].no, BLOCK_GROUP) return end --[[ 毎フレームこの関数がシステムから呼び出される ]] function MainLoop() PadRefresh() PadUpdate(0) Input = {GetPadStatus()} -- スコア処理 score = score + 1 if (high_score < score) then high_score = score end BlockMove() AliceMove() CheckHit() DrawFsTextLeft(font, 0, 0, 0, "HIGH SCORE", 0, DRAW_TO_SCREEN) DrawFsTextLeft(font, 0, 20, 0, high_score, 0, DRAW_TO_SCREEN) DrawFsTextLeft(font, 200, 0, 0, "SCORE", 0, DRAW_TO_SCREEN) DrawFsTextLeft(font, 200, 20, 0, score, 0, DRAW_TO_SCREEN) return end --[[ ブロック移動処理 ]] function BlockMove() -- すべてのオブジェクトを処理していく for i=1, #obj, 1 do -- 動かして MoveCheck(obj[i].no) -- 状態を取得して x, y = GetObjectPosition(obj[i].no) sizeX, sizeY = GetObjectSize(obj[i].no) vx, vy = GetObjectVelocityReal(obj[i].no) -- 表示 DrawTexture(block, x, y, sizeX,sizeY, 128, 0, sizeX, sizeY, 0, DRAW_TO_WORLD) -- 画面外にはみ出ようとするときは跳ね返す if (vx < 0 and x < 0) then -- 左に移動しているときに画面左からはみ出ようとしたら右へ跳ね返す vx = vx * -1 end -- 以下の処理は似たようなもの、単純に速度を反転させて追い返すのみ if (vy < 0 and y < 0) then vy = vy * -1 end if (vx > 0 and x + sizeX > 480) then vx = vx * -1 end if (vy > 0 and y + sizeY > 272) then vy = vy * -1 end -- 速度情報を更新 SetObjectVelocityReal(obj[i].no, vx, vy) end return end --[[ プレイヤーキャラの移動処理 ]] function AliceMove() vx, vy = 0, 0 -- ボタンを押してないときは移動させない speed = 300 -- 移動速度 -- キー入力をみて速度を与える if (Input[BUTTON_NUMBER_RIGHT] == BUTTON_STATUS_HOLD) then vx = speed end if (Input[BUTTON_NUMBER_LEFT] == BUTTON_STATUS_HOLD) then vx = -speed end if (Input[BUTTON_NUMBER_DOWN] == BUTTON_STATUS_HOLD) then vy = speed end if (Input[BUTTON_NUMBER_UP] == BUTTON_STATUS_HOLD) then vy = -speed end SetObjectVelocityReal(player.no, vx, vy) -- 動かして MoveCheck(player.no) -- 最新情報を得る x, y = GetObjectPosition(player.no) sizeX, sizeY = GetObjectSize(player.no) -- 画面外へは行かせない if (x < 0) then x = 0 end if (y < 0) then y = 0 end if (x + sizeX > 480) then x = 480 - sizeX end if (y + sizeY > 272) then y = 272 - sizeY end SetObjectPosition(player.no, x, y) -- 表示とアニメ処理 DrawAnimation(player.motion, player.pattern, x, y, 0, DRAW_TO_WORLD) player.motion, player.pattern, player.count, loop = CountAnimationPattern(player.motion, player.pattern, player.count, -1, 1, 1) return end --[[ 当たり判定チェック プレイヤーとブロックが衝突しているか調べる ]] function CheckHit() -- 当たり判定を行うとオブジェクトごとに衝突した相手のオブジェクト番号をひとつだけ記録する -- 新たに判定行って別のオブジェクトと衝突していたときは新しい相手の番号で記録を上書きする -- すべてのオブジェクトの当たり判定チェック結果をリセットする -- ClearAllHitCheck() -- -- 対象のオブジェクトについてのみ衝突判定の記録をリセット -- ClearHitCheck(id) -- 引数 -- id -- 対象となるオブジェクト番号 -- 対象のグループに属するオブジェクトすべての衝突判定の記録をリセット -- ClearGroppHitCheck(group) -- 引数 -- group -- 対象となる衝突判定グループ番号 -- ここではすべてのオブジェクトについて記録をリセットする ClearAllHitCheck() -- 衝突判定を行う -- -- 対象オブジェクトと特定グループに属するすべてのオブジェクトとの衝突判定を行う -- CheckObjectHitToGroup(id, group) -- 引数 -- id -- 判定対象のオブジェクト -- group -- 判定対象となるグループ番号 -- -- ここではプレイヤーキャラが敵と衝突しているか調べる CheckObjectHitToGroup(player.no, BLOCK_GROUP) -- オブジェクトとオブジェクトで判定を行うときは以下の通り -- -- CheckObjectHitToObject(id1, id2) -- 引数 -- id1 -- 対象となるオブジェクト番号その1 -- id2 -- 対象となるオブジェクト番号その2 -- -- 衝突判定を行った後は衝突先のオブジェクト番号が記録される -- 衝突がなかった場合は0が記録されている -- 衝突記録を見る -- hit = GetObjectHitCheckID(id) -- 引数 -- id -- 記録を見る対象のオブジェクト番号 -- 戻り値 -- hit -- オブジェクト番号idが衝突した先のオブジェクトの番号 -- id = GetObjectHitCheckID(player.no) -- 0以外ならば衝突したということ if (id ~= 0) then InitializeGame() end return end -- オブジェクトを使用するときはここから下の関数が必要になります -- オブジェクトが移動したときにブロックへ衝突したり -- ブロックが移動してオブジェクトに衝突したりなどのイベント時に呼び出される関数群です -- 現在は全部trueを返しておけばOK -- このサンプルでは以下の関数を省略しても動作しますが -- 呼び出す関数が見つからない、というエラーでログが一杯になります --[[ ブロックが動いてしがみつき中のオブジェクトにぶつかったとき呼ばれる ブロックは移動後の状態 ]] function MovingBlockHitToClimbingObject(id, box, tri, slope, top, moveX, moveY) return true end --[[ しがみつき中のオブジェクトが動いておぶじぇくとも移動するときに呼ばれる ブロックは移動後の状態 ]] function ClimbingObjectMovedByBlock(id, box, tri, slope, top, moveX, moveY) return true end --[[ 立っているブロックが動いたのでオブジェクトも移動するときに呼ばれる ブロックは移動後の状態 ]] function StandingObjectMovedByBlock(id, box, tri, slope, top, moveX, moveY) return true end --[[ ブロックが動いてオブジェクトにぶつかったときに呼ばれる しがみつき中にぶつかったときは別関数が呼ばれる オブジェクトもブロックも移動前の状態 ]] function MovingBlockHitToObject(id, box, tri, slope, top, moveX, moveY) return true end --[[ オブジェクト移動後にブロックへぶつかっているときに呼び出される ここでX,Yそれぞれの成分を0にしないと速度が保存されてブロックから離れた瞬間飛び出す 壁にぶつかって跳ね返るときは正負を逆にすれば良い 他には着地ブロックを見てあれやこれや 引数 id 対象となるオブジェクトID box, tri, slope, top ぶつかったブロックのID ただし、最初に衝突判定されたブロックIDのみ返すので 複数個に衝突したかどうか、引数だけではわからない ]] function MovedObjectHitToBlockForX(id, box, tri, slope, top) return true end function MovedObjectHitToBlockForY(id, box, tri, slope, top) return true end -- 空中からスロープへ移るとき function MovingObjectMoveToSlope(id, slope, velX, velY, floor, reaction) return true end -- 移動終了後、床から浮き上がる方向へ速度があるとき function MovedObjectVectorForAir(id, box, tri, slope, top, floor, reaction) return true end -- 別ブロックへ移ったときに呼び出される -- 法線ベクトル量も渡すので呼び出し側で床から浮き上がる処理とか行える -- 特に処理が必要なければtrueを返してライブラリに処理をさせる function MovingObjectChangeStandingPlace(id, box, tri, slope, top, floor, reaction) return true end -- 空中に居たオブジェクトが着地するか判定するとき呼び出される -- 普通はライブラリに任せるておけばよい function MovingObjectCheckStandOn(id) return true; end function MovingObjectMoveToAir(id) return true end