HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2013
0731
ieyasuhspdfixでスプライトを一旦オフスクリーンに描画する方法4解決


ieyasu

リンク

2013/7/31(Wed) 23:21:54|NO.56013

hspdfixでスプライトを一旦オフスクリーンに描画する方法が知りたいです。
一旦大きな別画面にスプライトとマップを描きこんだあと表示する分だけ切り取る形でのスクロールを行いたいのですが、
スプライトをオフスクリーンに書き込む方法が分からず困っています。

自機の動きに合わせてスプライトを反対側に動かす形でのスクロールも試してみましたが、
動く前の自機の位置に向けて移動するように命令したスプライト(自機に向けて発射された弾)が別の地点に到達してしまったりと、うまくいきませんでした。

どちらかだけでも解決できればいいので、情報があったらぜひ下さい。



この記事に返信する


ZAP

リンク

2013/7/31(Wed) 23:57:24|NO.56016

ここでいうオフスクリーンとは「es_buffer」で確保した裏画面、という解釈でよいですか?

スプライトは通常のコピーとは描画系統が別で、
DLL側で直接画面に書き込むことで高速化を図っている(と思われる)ので、
たぶん質問のようなやりかたは出来ないと思います。

いったんマップとキャラを重ね合わせたいのであれば、
スプライトを使用せずに通常の透過コピー(es_copy)でバッファに描画するように、
組み直す必要があると思います。

>動く前の自機の位置に向けて移動するように命令したスプライト(自機に向けて発射された弾)が
>別の地点に到達してしまったりと、うまくいきませんでした。

これはコピーの仕方というよりはキャラクターの座標管理の問題のような気がします。



ieyasu

リンク

2013/8/1(Thu) 12:23:55|NO.56019

>スプライトは通常のコピーとは描画系統が別で、
分かりやすくありがとうございます。参考になります。

>これはコピーの仕方というよりはキャラクターの座標管理の問題のような気がします。
きっとそうでしょう。しかし、原因を考えてみても分かりませんでした。
es_aimで移動を設定したスプライトをes_posすると何か不都合が発生するのでしょうか。
スクリプトはイメージとしては下記の通りなのですが、一体何が悪いのか。

;初期化----------------------------------------------------
#include "hspdxfix.as" #include "hsp3util.as" es_ini 1000,1000,360:es_screen 640,480,32,,1,1 screen 0,640,480,0 if stat : dialog"HSPDXFIX : DirectXの初期化に失敗":end *start gsel 0:mmstop:es_cls:es_draw:es_sync:wait 100 ;---------------------------------------------------------- ;****************** buffer 1:buffer 2:buffer 3 color $FF,$FF,0 mes"人・敵" es_buffer 1,2,$FFFFFF ;転送失敗時 if stat=1 { es_bye dialog "転送に失敗しました。",1,"Error" end } ;キャラクタ登録 es_size 16,20,80,0 es_pat 0,0,0,0 es_size 2,2,100,0 es_pat 1,23,7,0 es_size 16,20,90,0 es_pat 3,32,0,0 ;MAP設定 mapsize_x=1280:mapsize_y=480 buffer 5,mapsize_x,mapsize_y gsel 5 cls 4 color 255,255,255 mx=0:my=0 *map_draw pos mx*16,464 mes mx if mx<160:mx+=1:goto *map_draw es_buffer 5,2,$FFFFFF;window5に送る ;ステージ前初期化 chara_x=32:chara_y=448;自機座標の初期値設定 chara_wx=chara_x:chara_wy=chara_y window_x=0:window_y=0 ;----------敵配置---------- dim enemy_sdelay,99 enemy_sdelay=25,50 enemy_bbullet_no=300 benemy_no=201 es_set 200,432,292,3,0;432,236,3,0 es_set 201,432,236,3,0 ;メインルーチン------------------------------------- repeat ;移動関係 getkey a0,38:getkey a1,37:getkey a2,39 if a1=1{ chara_x-=3 if chara_x>312:if chara_x<mapsize_x-328:gosub *scroll_enemy_left:gosub *scroll_enemybullet_left } if a2=1{ chara_x+=3 if chara_x>312:if chara_x<mapsize_x-328:gosub *scroll_enemy_right:gosub *scroll_enemybullet_right } if chara_x<=0:chara_x=0 if chara_x>=mapsize_x-16:chara_x=mapsize_x-16 if chara_y<=0:chara_y=0 ;-----------敵処理----------- gosub *enemy_shot ;----------escキーで終了----------- getkey b,27 if b=1:es_bye:end ;------------描画ステップ------------ chara_wx=chara_x:chara_wy=chara_y;chara_x=キャラマップ座標 chara_wx=キャラ画面座標 window_x=chara_x-312;マップ切り取り開始位置座標調整 if window_x<0:window_x=0 if window_x>mapsize_x-640:window_x=mapsize_x-640 if chara_wx>312{ if chara_wx>mapsize_x-328{ chara_wx-=mapsize_x:chara_wx+=640 } else:chara_wx=312 } gsel 0 es_cls;画面クリア es_copy 5,window_x,window_y,640,480;ID5のwindowから画面全てコピー(マップ想定) es_set 0,chara_wx,chara_wy,0,0;自機スプライト描画準備 es_draw es_sync 16 ;------------------------------------ await 0 loop ;----------サブルーチン---------- ;-----------敵弾発射処理------------- *enemy_shot enemy_n=benemy_no if enemy_n<200:return *enemy_shot_loop es_get enemy_f,enemy_n,0 if enemy_f=0:if enemy_n>200{ if enemy_n=benemy_no:benemy_no-=1 enemy_n-=1:goto *enemy_shot_loop } else :return enemy_sdelay(enemy_n-200)-=1;敵機弾ディレイ値を減らす if enemy_sdelay(enemy_n-200)>0:if enemy_n>200{enemy_n-=1:goto *enemy_shot_loop} else :return enemy_sdelay(enemy_n-200)=10;ディレイリセット es_new enemy_bullet_no,300;空スプライトナンバー取得(No.300以降で検索) if enemy_bullet_no>enemy_bbullet_no{ enemy_bbullet_no=enemy_bullet_no;最大Noを記録しておく } es_get enemy_bullet_x,enemy_n,3 es_get enemy_bullet_y,enemy_n,5 es_set enemy_bullet_no,enemy_bullet_x+8,enemy_bullet_y+8,1,0;弾セット es_aim enemy_bullet_no,chara_wx+8,chara_wy+8,200;弾移動 if enemy_n>200:enemy_n-=1:goto *enemy_shot_loop return ;----------------------------------- ;----------敵スクロール---------- *scroll_enemy_left enemy_scroll_n=benemy_no if enemy_n<200:return *scroll_enemy_left_loop es_get enemy_scroll_f,enemy_scroll_n,0;fにn番のスプライトのフラグnoを代入 if enemy_scroll_f!0{;n番のフラグが立っている場合は(n番のスプライトが生きていれば) es_get enemy_scroll_x,enemy_scroll_n,3;xにn番のスプライトのx座標を代入 es_get enemy_scroll_y,enemy_scroll_n,5;yにn番のスプライトのy座標を代入 es_pos enemy_scroll_n,enemy_scroll_x+3,enemy_scroll_y;該当スプライトをx方向に3ずらす } else:if enemy_scroll_n=benemy_no:benemy_no-=1 if enemy_scroll_n>200:enemy_scroll_n-=1:goto *scroll_enemy_left_loop;最大noから開始して最低noまでチェックしてなかったらloop return *scroll_enemy_right enemy_scroll_n=benemy_no if enemy_n<200:return *scroll_enemy_right_loop es_get enemy_scroll_f,enemy_scroll_n,0;fにn番のスプライトのフラグnoを代入 if enemy_scroll_f!0{;n番のフラグが立っている場合は(n番のスプライトが生きていれば) es_get enemy_scroll_x,enemy_scroll_n,3;xにn番のスプライトのx座標を代入 es_get enemy_scroll_y,enemy_scroll_n,5;yにn番のスプライトのy座標を代入 es_pos enemy_scroll_n,enemy_scroll_x-3,enemy_scroll_y;該当スプライトをxの逆に3ずらす } else:if enemy_scroll_n=benemy_no:benemy_no-=1 if enemy_scroll_n>200:enemy_scroll_n-=1:goto *scroll_enemy_right_loop;最大noから開始して最低noまでチェックしてなかったらloop return ;----------敵弾スクロール---------- *scroll_enemybullet_left enemy_scroll_bullet_n=enemy_bbullet_no if enemy_scroll_bullet_n<300:return *scroll_enemybullet_left_loop es_get enemy_scroll_bullet_f,enemy_scroll_bullet_n,0;fにn番のスプライトのフラグnoを代入 if enemy_scroll_bullet_f!0{;n番のフラグが立っている場合は(n番のスプライトが生きていれば) es_get enemy_scroll_bullet_x,enemy_scroll_bullet_n,3;xにn番のスプライトのx座標を代入 es_get enemy_scroll_bullet_y,enemy_scroll_bullet_n,5;yにn番のスプライトのy座標を代入 es_pos enemy_scroll_bullet_n,enemy_scroll_bullet_x+3,enemy_scroll_bullet_y;該当スプライトをx方向に3ずらす } else:if enemy_scroll_bullet_n=enemy_bbullet_no:enemy_bbullet_no-=1 if enemy_scroll_bullet_n>300:enemy_scroll_bullet_n-=1:goto *scroll_enemybullet_left_loop;最大noから開始して最低noまでチェックしてなかったらloop return *scroll_enemybullet_right enemy_scroll_bullet_n=enemy_bbullet_no if enemy_scroll_bullet_n<300:return *scroll_enemybullet_right_loop es_get enemy_scroll_bullet_f,enemy_scroll_bullet_n,0;fにn番のスプライトのフラグnoを代入 if enemy_scroll_bullet_f!0{;n番のフラグが立っている場合は(n番のスプライトが生きていれば) es_get enemy_scroll_bullet_x,enemy_scroll_bullet_n,3;xにn番のスプライトのx座標を代入 es_get enemy_scroll_bullet_y,enemy_scroll_bullet_n,5;yにn番のスプライトのy座標を代入 es_pos enemy_scroll_bullet_n,enemy_scroll_bullet_x-3,enemy_scroll_bullet_y;該当スプライトをxの逆に3ずらす } else:if enemy_scroll_bullet_n=enemy_bbullet_no:enemy_bbullet_no-=1 if enemy_scroll_bullet_n>300:enemy_scroll_bullet_n-=1:goto *scroll_enemybullet_right_loop;最大noから開始して最低noまでチェックしてなかったらloop return ;-------------------------------------



暇人

リンク

2013/8/1(Thu) 19:40:56|NO.56025

>es_aimで移動を設定したスプライトをes_posすると何か不都合が発生するのでしょうか。
es_aimは%で1フレームの移動量を指定できるようにしてるので
内部では固定小数点が使われてる
それをes_posで座標を指定してしまうと、小数部分が0でクリアされてしまうため
動きがおかしくなる

> es_get enemy_scroll_bullet_x,enemy_scroll_bullet_n,3;xにn番のスプライトのx座標を代入
これは整数部のみ取り出してるが
設定も同じ事が出来る

es_setp enemy_scroll_bullet_n,3,enemy_scroll_bullet_x-3
これで小数部はクリアせずに座標を設定できる
因みにスプライトのX座標を取得するのに3を指定してるのを2にすると小数部が取得できる(Yは4)

後、es_screen にDirect3Dを使う設定してるのに
他の命令が使用しない指定をしてるため物凄く重くなってる
自分の環境でNO.56019のスクリプトはCPU使用率45%(2コアなので実質90%)
全てDirect3D使用の指定をした場合0%になる

;初期化---------------------------------------------------- #include "hspdxfix.as" #include "hsp3util.as" es_ini 1000,1000,360:es_screen 640,480,32,,1,1 screen 0,640,480,0 if stat : dialog"HSPDXFIX : DirectXの初期化に失敗":end *start gsel 0:mmstop:es_cls:es_draw:es_sync:wait 100 ;---------------------------------------------------------- ;****************** buffer 1:buffer 2:buffer 3 color $FF,$FF,0 mes"人・敵" es_buffer 1,2,$FFFFFF,,1 ;転送失敗時 if stat=1 { es_bye dialog "転送に失敗しました。",1,"Error" end } ;キャラクタ登録 es_size 16,20,80,0 es_pat 0,0,0,0 es_size 2,2,100,0 es_pat 1,23,7,0 es_size 16,20,90,0 es_pat 3,32,0,0 ;MAP設定 mapsize_x=1280:mapsize_y=480 buffer 5,mapsize_x,mapsize_y gsel 5 cls 4 color 255,255,255 mx=0:my=0 *map_draw pos mx*16,464 mes mx if mx<160:mx+=1:goto *map_draw es_buffer 5,2,$FFFFFF,,1;window5に送る ;ステージ前初期化 chara_x=32:chara_y=448;自機座標の初期値設定 chara_wx=chara_x:chara_wy=chara_y window_x=0:window_y=0 ;----------敵配置---------- dim enemy_sdelay,99 enemy_sdelay=25,50 enemy_bbullet_no=300 benemy_no=201 es_set 200,432,292,3,1;432,236,3,0 es_set 201,432,236,3,1 ;メインルーチン------------------------------------- repeat ;移動関係 getkey a0,38:getkey a1,37:getkey a2,39 chara_speedx=a2*3-a1*3 if chara_speedx { chara_x+chara_speedx if chara_x>312:if chara_x<mapsize_x-328:gosub *scroll_enemy:gosub *scroll_enemybullet } if chara_x<=0:chara_x=0 if chara_x>=mapsize_x-16:chara_x=mapsize_x-16 if chara_y<=0:chara_y=0 ;-----------敵処理----------- gosub *enemy_shot ;----------escキーで終了----------- getkey b,27 if b=1:es_bye:end ;------------描画ステップ------------ chara_wx=chara_x:chara_wy=chara_y;chara_x=キャラマップ座標 chara_wx=キャラ画面座標 window_x=chara_x-312;マップ切り取り開始位置座標調整 if window_x<0:window_x=0 if window_x>mapsize_x-640:window_x=mapsize_x-640 if chara_wx>312{ if chara_wx>mapsize_x-328{ chara_wx-=mapsize_x:chara_wx+=640 } else:chara_wx=312 } gsel 0 ;es_cls;画面クリア es_excopy 5,window_x,window_y,640,480;ID5のwindowから画面全てコピー(マップ想定) es_set 0,chara_wx,chara_wy,0,1;自機スプライト描画準備 es_draw es_sync 16 ;------------------------------------ await 0 loop ;----------サブルーチン---------- ;-----------敵弾発射処理------------- *enemy_shot enemy_n=benemy_no if enemy_n<200:return *enemy_shot_loop es_get enemy_f,enemy_n,0 if enemy_f=0:if enemy_n>200{ if enemy_n=benemy_no:benemy_no-=1 enemy_n-=1:goto *enemy_shot_loop } else :return enemy_sdelay(enemy_n-200)-=1;敵機弾ディレイ値を減らす if enemy_sdelay(enemy_n-200)>0:if enemy_n>200{enemy_n-=1:goto *enemy_shot_loop} else :return enemy_sdelay(enemy_n-200)=10;ディレイリセット es_new enemy_bullet_no,300;空スプライトナンバー取得(No.300以降で検索) if enemy_bullet_no>enemy_bbullet_no{ enemy_bbullet_no=enemy_bullet_no;最大Noを記録しておく } es_get enemy_bullet_x,enemy_n,3 es_get enemy_bullet_y,enemy_n,5 es_set enemy_bullet_no,enemy_bullet_x+8,enemy_bullet_y+8,1,1;弾セット es_aim enemy_bullet_no,chara_wx+8,chara_wy+8,200;弾移動 if enemy_n>200:enemy_n-=1:goto *enemy_shot_loop return ;----------------------------------- ;----------敵スクロール---------- *scroll_enemy enemy_scroll_n=benemy_no if enemy_n<200:return *scroll_enemy_loop es_get enemy_scroll_f,enemy_scroll_n,0;fにn番のスプライトのフラグnoを代入 if enemy_scroll_f!0{;n番のフラグが立っている場合は(n番のスプライトが生きていれば) es_get enemy_scroll_x,enemy_scroll_n,3;xにn番のスプライトのx座標を代入 es_setp enemy_scroll_n,3,enemy_scroll_x-chara_speedx;該当スプライトをx方向にchara_speed分ずらす } else:if enemy_scroll_n=benemy_no:benemy_no-=1 if enemy_scroll_n>200:enemy_scroll_n-=1:goto *scroll_enemy_loop;最大noから開始して最低noまでチェックしてなかったらloop return ;----------敵弾スクロール---------- *scroll_enemybullet enemy_scroll_bullet_n=enemy_bbullet_no if enemy_scroll_bullet_n<300:return *scroll_enemybullet_loop es_get enemy_scroll_bullet_f,enemy_scroll_bullet_n,0;fにn番のスプライトのフラグnoを代入 if enemy_scroll_bullet_f!0{;n番のフラグが立っている場合は(n番のスプライトが生きていれば) es_get enemy_scroll_bullet_x,enemy_scroll_bullet_n,3;xにn番のスプライトのx座標を代入 es_setp enemy_scroll_bullet_n,3,enemy_scroll_bullet_x-chara_speedx;該当スプライトをx方向にchara_speed分ずらす } else:if enemy_scroll_bullet_n=enemy_bbullet_no:enemy_bbullet_no-=1 if enemy_scroll_bullet_n>300:enemy_scroll_bullet_n-=1:goto *scroll_enemybullet_loop;最大noから開始して最低noまでチェックしてなかったらloop return
全部Direct3D使用するようにして
左右のスクロールでサブルーチンの差異が移動量だけなので一緒にした



ieyasu

リンク

2013/8/1(Thu) 20:53:49|NO.56027

とても分かりやすく詳細な説明をありがとうございます。
勉強不足でお手数をおかけしました!



ONION software Copyright 1997-2021(c) All rights reserved.