我正在尝试开发一个老式的NES风格的视频游戏,精灵闪烁和图形减速.我一直在想我应该用什么类型的逻辑来启用这样的效果.
如果我想要老式的NES风格,我必须考虑以下限制:
从我读过的内容来看,如果屏幕上有超过64个精灵,开发人员只会绘制高优先级精灵而忽略低优先级精灵.它们也可以交替,在奇数编号的相对帧上绘制每个偶数编号的精灵.
扫描线问题很有意思.从我的测试来看,通过像NES那样逐个像素地绘制精灵,不可能在XBOX 360 XNA框架上获得良好的速度.这就是为什么在老式游戏中,如果在一条线上有太多的精灵,如果它们被减半,就会出现一些.对于这个项目的所有目的,我将扫描线设置为8像素高,并通过Y定位将每个扫描线的精灵分组在一起.
为了澄清,我将以8x8像素,而不是1x1的批量绘制精灵到屏幕.
所以,愚蠢的我需要提出一个解决方案....
这是我目前的理论
首先,我提出的一个基本想法是解决精灵优先级问题.假设0-255(0为低)之间的值,我可以分配精灵优先级,例如:
在我的数据文件中,我可以将每个精灵分配为特定优先级.创建父对象时,精灵将在其指定范围之间随机分配一个数字.然后我会按照从高到低的顺序绘制精灵,最终目标是绘制每个精灵.
现在,当一个精灵被绘制在一个帧中时,我会在其初始优先级内随机生成一个新的优先级值.但是,如果没有在帧中绘制精灵,我可以将32添加到其当前优先级.例如,如果该系统可只画出精灵下降到135的优先级,具有45°的初始优先级的子画面然后可以后不被抽的3帧绘制(45 + 32 + 32 + 32 = 141)
理论上,这将允许精灵交替帧,允许优先级,并将精灵限制为每个屏幕64个.
现在,有趣的问题是我如何将精灵限制为每个扫描线只有8个?
我想如果我将精灵高优先级排序为低优先级,则循环遍历循环直到我达到64个精灵.但是,我不应该只列出列表中的前64个精灵.
在绘制每个精灵之前,我可以通过计数器变量检查在它的相应扫描线中绘制了多少个精灵.例如:
我可以为每个绘制的帧重置每条扫描线的值.在向下精灵列表的同时,如果在该扫描线中绘制了精灵,则向扫描线的相应计数器添加1.如果它等于8,则不绘制该精灵并转到具有下一个最低优先级的精灵.
慢一点
我需要做的最后一件事是模拟减速.我最初的想法是,如果我每帧绘制64个精灵并且还需要绘制更多的精灵,我可以将渲染暂停16ms左右.然而,在我玩过的NES游戏中,如果没有任何精灵闪烁,有时会减速,而即使有一些精灵闪烁,游戏也会漂亮地移动.
也许为每个在屏幕上使用精灵的对象赋予一个值(比如上面的优先级值),如果所有对象的组合值都超过阈值,那么引入减速?
结论...
我写的所有内容听起来是否合法且可行,或者它是一个白日梦吗?我可以用这个游戏编程理论思考哪些改进?
我想知道NES如何显示其图形肌肉.我已经在线研究过这些东西,并通过它阅读,但我想知道最后一件事:Nametables.
基本上,根据我的阅读,NES名称表中的每个8x8块指向模式表中的一个位置,该位置保存图形内存.此外,名称表还有一个属性表,为每个16x16块设置特定的调色板.他们像这样联系在一起:
(假设16个8x8块)Nametable,ABCD =指向精灵数据的指针:
ABBB
CDCC
DDDD
DDDD
Run Code Online (Sandbox Code Playgroud)
属性表,1 2 3 =指向调色板数据的指针,<左侧引用值,上方^,左侧和上方:
1<2<
^'^'
3<3<
^'^'
Run Code Online (Sandbox Code Playgroud)
因此,在上面的示例中,块将被着色
1A 1B 2B 2B
1C 1D 2C 2C
3D 3D 3D 3D
3D 3D 3D 3D
Run Code Online (Sandbox Code Playgroud)
现在,如果我在固定的屏幕上有这个 - 它很棒!因为NES分辨率是256x240像素.现在,这些表如何调整滚动?
因为Nametable 0可以滚动到Nametable 1,如果你继续滚动Nametable 0将再次回滚.我得到了.但我没有得到的是如何滚动属性表包装.从我在网上看到的情况来看,它分配属性的16x16块会导致屏幕边缘区域的颜色失真(如左右滚动时反映,SMB3反之亦然).
我关心的是我了解如何滚动名称表,但是如何滚动属性表?对于intsance,如果我在屏幕的左侧有一个绿色块,将屏幕向右移动理论上应该使右侧的瓷砖变为绿色,直到它们移动到框架中,然后它们将恢复到他们的正常颜色.
~~~~编辑:我想指出我知道扫描线,X和Y.这个想法刚刚贯穿我的脑海.
假设我的扫描线Y为10.这意味着我正在水平地读取10个值到我的名字表中.这意味着我的第一列不在屏幕上,因为它只有8的像素宽度.但是,颜色属性保持不变,因为它的宽度为16.
假设整个列的颜色属性为绿色,我认为对用户来说是正确的,屏幕左边的前6个像素是绿色,屏幕最右边的10个也应该是绿色的?那么,根据屏幕,左边的假设我是否正确?
给出以下XML文件:
<?xml version="1.0" encoding="UTF-8"?>
<application name="foo">
<movie name="tc" english="tce.swf" chinese="tcc.swf" a="1" b="10" c="20" />
<movie name="tl" english="tle.swf" chinese="tlc.swf" d="30" e="40" f="50" />
</application>
Run Code Online (Sandbox Code Playgroud)
如何访问MOVIE节点的属性("英语","中文","名称","a","b"等)及其相关值?我目前在Cocoa中有遍历这些节点的能力,但我对如何访问MOVIE NSXMLNodes中的数据感到茫然.
有没有办法可以将每个NSXMLNode中的所有值转储到Hashtable中并以这种方式检索值?
我使用的是NSXMLDocument和NSXMLNodes.
我目前正在用C#编写一个基本上可以称为我自己对NES硬件的解释,用于我正在开发的老式游戏.我已经解雇了FCE并且一直在观察NES如何显示和渲染图形.
简而言之,NES可以保存两个位图值的图形信息,每个图形信息的尺寸为128x128.这些被称为PPU表.一个用于BG瓷砖,另一个用于精灵.数据必须在此内存中才能在屏幕上绘制.现在,如果一个游戏有更多的图形数据然后这两个银行,它可以将这些新信息的一部分写入这些银行 - 在每一帧的末尾覆盖那里的东西 - 并从下一帧开始使用它.
那么,在旧游戏中,程序员的银行如何切换?我的意思是,在关卡设计中,他们是如何知道要加载哪个图形集的?当屏幕以编程方式从舞台的一部分滚动到下一部分时,我注意到Mega Man 2银行开关.但他们是如何将这些信息存储在关卡中的 - 将哪些精灵复制到PPU表中,以及在哪里写入?
另一个例子是在MM2中暂停.暂停期间BG块会被覆盖,然后在玩家取消暂停时恢复.他们是如何记住他们更换了哪些瓷砖以及如何恢复它们?
如果我是懒惰的,我可以制作一个巨大的静态位图,然后就这样获取值.但我强迫自己限制这些价值观,以创造更真实的体验.我已经阅读了有关MC Kids如何制作的精彩指南,并且我正试图成为关于我如何编程这个游戏的准系统.我仍然只是想到这些程序员如何完成他们所做的事情.
编辑:我能想到的唯一解决方案是保存单独的表,说明PPU在什么时间应该在哪些瓷砖,但我认为这将是NES无法处理的巨大内存资源.
我总是想知道最简单的方法来确定一个点是否在一个三角形内,或者在这种情况下,一个矩形对角切成两半.
假设我有一个64x64像素的矩形.使用此矩形,如果传递的点位于矩形的左上角,我想返回TRUE值,如果不是,则返回FALSE.
-----
| /|
| / |
|<__|
Run Code Online (Sandbox Code Playgroud)
霍瑞为糟糕的ASCII艺术.
无论如何,这个返回TRUE的三角形的假设点将是(0,0)和(63,0)和(0,63).如果一个点落在一条线上(例如,50,0),它也将返回TRUE.
假设0,0位于左上角并向下增加......
我脑子里有一个可能的解决方案,但它似乎比它应该更复杂 - 获取传递的Y值,确定它在矩形中的位置,并手动计算出该线在该Y值处切割的位置.例如,传递的Y值为16将是矩形的四分之一高度.因此,根据您检查的哪一侧(左侧或右侧),线条将为16px或48px,具体取决于线的方向. 在上面的示例中,由于我们正在测试左上角,高度为16px,因此线宽为48px
一定有更好的方法.
编辑:矩形也可能看起来像这样
-----
|\ |
| \ |
|__>|
Run Code Online (Sandbox Code Playgroud)
但我在大多数情况下都认为目前已经提供的答案仍应该坚持......
我试图弄清楚如何在XNA中绘制图形,而其他人建议这样做.但在我尝试使用之前......
如果我创建并使用此相机,并将LEFT,TOP设置为0,WIDTH = 256和HEIGHT = 240,我渲染到屏幕的任何内容都将使用这些坐标?所以一个宽度和高度为1的盒子,如果设置为0,0将占用0,0到1,1的空间?
这是我正在尝试开发的代码:
Public Structure Statistic(Of t)
Dim maxStat As t
Dim curStat As t
Public Sub New(ByVal pValue As t)
maxStat = pValue
curStat = pValue
End Sub
Public Property Level() As t
Get
Return curStat
End Get
Set(ByVal value As t)
curStat = value
If curStat > maxStat Then curStat = maxStat
End Set
End Property
End Structure
Run Code Online (Sandbox Code Playgroud)
它不会编译,因为我收到一个错误,'>'没有为T和T的类型定义.无论如何,我可以指定约束,保证T是一个数字类型?
这是我在用户进行更改和建议后目前所拥有的.它仍然无法正常工作.我是否必须将T的值更改为IComparable?必须有一些非常简单的东西,我搞砸了.
Public Structure Statistic(Of T As IComparable(Of T))
Dim maxStat As T
Dim curStat As T
Public Sub New(ByVal pValue As …
Run Code Online (Sandbox Code Playgroud) 我正在查看Apple的文档,我似乎无法找到一种方法来判断MPMediaItem是否是"最喜欢的"曲目.用粉红色的心看下面的截图.
怎么能得到这个属性?我知道,因为它是一个新功能,它的可用性仅限于iOS 8.4或更高版本.
这里有一些代码,我用它来通过音乐选择器从MPMediaItems获取其他属性:
- (void) processMediaItems:(MPMediaItemCollection *)mediaItemCollection
{
//iterate through selected songs
if (mediaItemCollection) {
NSArray *allSelectedSongs = [mediaItemCollection items];
for(MPMediaItem *song in allSelectedSongs)
{
NSURL *songURL = [song valueForProperty:MPMediaItemPropertyAssetURL];
NSNumber *ident = [song valueForProperty:MPMediaEntityPropertyPersistentID];
NSString *identString = [BukketHelper convertULLToNSString:ident];
NSNumber *isCloud = [song valueForProperty:MPMediaItemPropertyIsCloudItem];
}
//do other stuff here
}
Run Code Online (Sandbox Code Playgroud)
有人有想法吗?
我在使用Cocoa创建新窗口时遇到问题.假设,假设我有"WindowA",并有一个名为"myButton"的按钮.当您单击"myButton"时,它会在以下类文件中运行此代码:
-(void)openFile2:(id)sender
{
myNextWindow = [[TestWindowController alloc] initWithWindowNibName:@"MainMenu"];
NSString *testString = @"foo";
[myNextWindow showWindow:self];
[myNextWindow setButtonText:testString];
}
Run Code Online (Sandbox Code Playgroud)
简而言之,代码会复制"WindowA"并显示它.如您所见,此代码还运行一个名为'setButtonText'的方法,它是这样的:
- (void)setButtonText:(NSString *)passedText
{
[myButton setTitle:passedText];
}
Run Code Online (Sandbox Code Playgroud)
问题是,当我在本地调用此方法时,在原始窗口中 - 按钮文本更改(例如,[self setButtonText:testString])它可以工作.但是,它在新创建的窗口中不起作用(例如,[myNextWindow setButtonText:testString];)
当我逐步调试新创建的窗口时,它给出的'myButton'值是0x0.我是否必须手动将控制器/代理分配给新窗口?我认为代码中的'myButton'与新创建的窗口中的'myButton'没有关联.
我该如何解决这个问题?