- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
这可能需要一些解释,但在这里,非常感谢任何见解。
简短版本:如何创建一个 TouchableButton(它自己检测触摸),其 CCSprite 图像是另一个类中 CCSpriteBatchNode 的子节点? (通常 CCSprite 是 TouchableButton 本身的子项)。
长版:
我正在使用 Cocos2d 构建游戏。该游戏着重于一个充满代理(AgentView 类:CCNode)的景观(类 EnvironmentView:CCLayer),这些代理(类 AgentView:CCNode)四处奔跑并相互交互。
EnvironmentView 维护一个 AgentView 对象列表并根据需要创建/销毁它们(取决于它们的交互方式)。
每个 AgentView 都有一个 CCSprite @property,它被添加为 CCBatchNode 的子节点(EnvironmentView 的 @property),后者被添加为 EnvironmentView 的子节点。
我正在尝试实现一项功能,让用户可以触摸代理并将它们从景观中的一个地方移动到另一个地方。
因为有很多代理在 EnvironmentView 中四处移动,所以我不想使用标准方法获取触摸位置并循环遍历所有 AgentView CCSprite 以查看触摸是否击中其中之一(这会降低帧率相当大,请:对促进这种方法的答案不感兴趣)。
相反,我想让每个 AgentView 成为一个可触摸节点(一个知道何时被触摸的节点,而不是一个被告知何时被触摸的节点(上述方法))。
基本上,我想用某种 TouchableButton 对象替换或扩充每个 AgentView 的 CCSprite。
我正在使用一个类(我们称它为 TouchableButton),该类将这种方法用于我游戏中与 UI 相关的按钮,它们知道何时被触摸,而无需在其父层中实现任何 CCTouchesBegan 方法。但是我一直无法为这个用例调整 TouchableButton,原因如下:
TouchableButtons 将 CCSprite 作为初始参数。此 CCSprite 设置为按钮的可触摸部分,并作为按钮本身的子项添加。因为我还在 EnvironmentView 中将 CCSprite 添加为 CCSpriteBatchNode 的子对象,所以我收到一个错误(无法将某些东西作为子对象添加两次到两个不同的父对象)。我如何构建事物以避免这种冲突?
在此先感谢您的帮助!
最佳答案
简短的回答:你不能。
长答案:您可以获得相同的效果,但方式不同。
CCSpriteBatchNode 的工作原理是在具有公共(public)纹理( Sprite 表)的单个 glDrawElements 调用中绘制其所有 CCSprite 子节点,这就是它具有如此出色性能的原因。但结果是,每个 child 都必须是 Sprite ,如果您将 child 添加到 Sprite 中,它将被忽略。
因此,此时您唯一的办法是将 CCSprite 子类化为按钮并复制很多功能,如下所示:
按钮 Sprite .h:
//
// ButtonSprite.h
// TestButtonSprite
//
// Created by Karl Stenerud on 9/1/11.
//
#import "cocos2d.h"
@class ButtonSprite;
typedef void (^ButtonPressCallback)(ButtonSprite* button);
/**
* A sprite that can respond to touches.
* Most of this code was taken from CCLayer.
*/
@interface ButtonSprite : CCSprite <CCStandardTouchDelegate, CCTargetedTouchDelegate>
{
BOOL touchEnabled_;
int touchPriority_;
BOOL swallowTouches_;
BOOL registeredWithDispatcher_;
BOOL touchInProgress_;
BOOL buttonWasDown_;
ButtonPressCallback onButtonPressedCallback_;
}
/** Priority position in which this node will be handled (lower = sooner) */
@property(nonatomic,readwrite,assign) int touchPriority;
/** If true, no other node will respond to touches this one responds to */
@property(nonatomic,readwrite,assign) BOOL swallowTouches;
/** If true, this node responds to touches. */
@property(nonatomic,readwrite,assign) BOOL touchEnabled;
/** Called whenever a full touch completes */
@property(nonatomic,readwrite,copy) ButtonPressCallback onButtonPressedCallback;
/** Called when a button press is detected. */
- (void) onButtonPressed;
/** Called when a button is pushed down. */
- (void) onButtonDown;
/** Called when a button is released. */
- (void) onButtonUp;
- (BOOL) touchHitsSelf:(UITouch*) touch;
- (BOOL) touch:(UITouch*) touch hitsNode:(CCNode*) node;
@end
ButtonSprite.m:
//
// ButtonSprite.m
// TestButtonSprite
//
// Created by Karl Stenerud on 9/1/11.
//
#import "ButtonSprite.h"
@interface ButtonSprite ()
- (void) registerWithTouchDispatcher;
- (void) unregisterWithTouchDispatcher;
@end
@implementation ButtonSprite
@synthesize touchEnabled = touchEnabled_;
@synthesize touchPriority = touchPriority_;
@synthesize swallowTouches = swallowTouches_;
@synthesize onButtonPressedCallback = onButtonPressedCallback_;
- (id) init
{
if(nil != (self = [super init]))
{
touchPriority_ = 0;
swallowTouches_ = YES;
touchEnabled_ = YES;
self.isRelativeAnchorPoint = YES;
self.anchorPoint = ccp(0.5, 0.5);
}
return self;
}
- (void) dealloc
{
[self unregisterWithTouchDispatcher];
[onButtonPressedCallback_ release];
[super dealloc];
}
- (void) registerWithTouchDispatcher
{
[self unregisterWithTouchDispatcher];
[[CCTouchDispatcher sharedDispatcher] addTargetedDelegate:self priority:self.touchPriority swallowsTouches:self.swallowTouches];
registeredWithDispatcher_ = YES;
}
- (void) unregisterWithTouchDispatcher
{
if(registeredWithDispatcher_)
{
[[CCTouchDispatcher sharedDispatcher] removeDelegate:self];
registeredWithDispatcher_ = NO;
}
}
- (void) setSwallowTouches:(BOOL) value
{
if(swallowTouches_ != value)
{
swallowTouches_ = value;
if(isRunning_ && touchEnabled_)
{
[self registerWithTouchDispatcher];
}
}
}
- (void) setTouchPriority:(int) value
{
if(touchPriority_ != value)
{
touchPriority_ = value;
if(isRunning_ && touchEnabled_)
{
[self registerWithTouchDispatcher];
}
}
}
-(void) setTouchEnabled:(BOOL)enabled
{
if( touchEnabled_ != enabled )
{
touchEnabled_ = enabled;
if( isRunning_ )
{
if( touchEnabled_ )
{
[self registerWithTouchDispatcher];
}
else
{
[self unregisterWithTouchDispatcher];
}
}
}
}
- (void)cleanup
{
self.touchEnabled = NO;
}
#pragma mark TouchableNode - Callbacks
-(void) onEnter
{
// register 'parent' nodes first
// since events are propagated in reverse order
if (self.touchEnabled)
{
[self registerWithTouchDispatcher];
}
// then iterate over all the children
[super onEnter];
}
-(void) onExit
{
if(self.touchEnabled)
{
[self unregisterWithTouchDispatcher];
}
[super onExit];
}
-(BOOL) ccTouchBegan:(UITouch *)touch withEvent:(UIEvent *)event
{
if([self touchHitsSelf:touch])
{
touchInProgress_ = YES;
buttonWasDown_ = YES;
[self onButtonDown];
return YES;
}
return NO;
}
-(void) ccTouchMoved:(UITouch *)touch withEvent:(UIEvent *)event
{
if(touchInProgress_)
{
if([self touchHitsSelf:touch])
{
if(!buttonWasDown_)
{
[self onButtonDown];
}
}
else
{
if(buttonWasDown_)
{
[self onButtonUp];
}
}
}
}
-(void) ccTouchEnded:(UITouch *)touch withEvent:(UIEvent *)event
{
if(buttonWasDown_)
{
[self onButtonUp];
}
if(touchInProgress_ && [self touchHitsSelf:touch])
{
touchInProgress_ = NO;
[self onButtonPressed];
}
}
-(void) ccTouchCancelled:(UITouch *)touch withEvent:(UIEvent *)event
{
if(buttonWasDown_)
{
[self onButtonUp];
}
touchInProgress_ = NO;
}
- (void) onButtonDown
{
buttonWasDown_ = YES;
}
- (void) onButtonUp
{
buttonWasDown_ = NO;
}
- (void) onButtonPressed
{
self.onButtonPressedCallback(self);
}
- (BOOL) touchHitsSelf:(UITouch*) touch
{
return [self touch:touch hitsNode:self];
}
- (BOOL) touch:(UITouch*) touch hitsNode:(CCNode*) node
{
CGRect r = CGRectMake(0, 0, node.contentSize.width, node.contentSize.height);
CGPoint local = [node convertTouchToNodeSpace:touch];
return CGRectContainsPoint(r, local);
}
@end
像这样使用它:
ButtonSprite* myButton = [ButtonSprite spriteWithFile:@"button_image.png"];
myButton.onButtonPressedCallback = ^(ButtonSprite* button)
{
NSLog(@"Pressed!");
};
[self addChild: myButton];
请注意,如果您在批处理节点中使用此类,则它不得有自己的任何子节点!
关于ios - 创建其 CCSprites 是 CCBatchNode 的子节点的可触摸 CCNode 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7271719/
我该怎么做 touch R 中的文件(即更新其修改时间而不更改其内容)?我正在寻找一个跨平台的内置(或打包)等效于: system2("touch", file_name) 最佳答案 我找到了 an
我想在 android 中实现 body 部位选择。我的要求是,当我点击特定部分时,图像应用程序应该能够识别 body 部位并且所选部分的颜色应该改变。附上示例图像以供引用。 如有任何想法或建议,我们
我需要将3D模型加载到我的应用程序中(不是游戏,它没有任何区别),并检测用户何时触摸此模型的特定部分以采取不同的操作。 我怎样才能做到这一点?可能吗? 最佳答案 我不熟悉Rajawali,但GitHu
似乎连续触摸总是被它起源的控件捕获。是否有标准方法将触摸/手势传递给当前触摸结束的控件? 最佳答案 控件显示在 UIView 对象内部的屏幕上。 iOS 使用第一响应者的概念来处理 UIView 对象
我有一个 UIScrollView 实例,允许用户放大/缩小。我已经根据文档实现了一个委托(delegate)来处理这个问题。但是,我想知道用户触摸 ScrollView 的位置(相对于 Scroll
我正在创建一款射击游戏,您可以触摸屏幕,玩家可以射击。我遇到的问题是,当你触摸屏幕并按住它并拖动它时,它会快速射击。处理这个问题的最佳方法是什么? 我希望玩家能够按住手指并以稳定的速度射击,而手指向上
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typ
这是我从触摸事件中获得的返回数据。明显缺少任何有用的触摸 X/Y 坐标 ( https://developer.mozilla.org/en-US/docs/Web/API/TouchEvent/ch
因此,我有一个屏幕,其中包含 0 到 6 个通过 XML 包含的相同用户界面组件。类似这样的东西: ...等等 每个包含的 UI 都是我重复使用的几个小部件和自定义组件的集
我希望能够更改文件的修改日期以便在 Web 应用程序中使用。目前我直接在命令行上测试这个。在我的 Mac 上工作正常,但是当我在 Linux 服务器上执行此操作时出现错误。 命令:/bin/touch
概念问题: 我在使用 touches 时遇到了一个非常简单的问题属性,自动更新依赖模型的时间戳;它正确地这样做了,但也应用了全局范围。 有什么办法可以关闭这个功能吗?或专门询问自动 touches忽略
我很难在一个简单的等距 Sprite Kit 游戏中实现点击处理。 我有一个包含多个 Tile 对象(SKSpriteNode)的 map (SKNode)的游戏场景(SKScene)。 这是 map
有没有办法在触摸事件后恢复 Flexslider 幻灯片的自动播放?现在看来,一旦我滑动导航,幻灯片就会停止...... 最佳答案 FLEXISLIDER 2 更新 resume()事件不再存在,正确
有些游戏有一些小图片作为 Sprite ,可以通过触摸来移动。如果 Sprite 是较大的图片,触摸是很正常的。我们可以使用函数CGRectContainsPoint检查 Sprite 。但是当 Sp
我有一个 View 覆盖到 iPhone 的相机 View 上。在此 View 中,我有一些 uibuttons,它们显示的位置取决于加速度计/指南针的值。当用户在 View 内触摸但没有在 uibu
我有一个 UIView 和一个 UIWebView。 UIWebView 是 UIView 的 subview 。 UIWebView 包含 YouTube 视频,并设置为让视频适合 UIWebVie
我是通过 XCode 使用 SDK 版本 5.0 进行 iOS 开发的新手。在我的应用程序中,我需要在按下按钮时更改按钮的标题。 假设在正常状态下它是“未推送”的。我所需要的是,当我按下按钮时,按钮标
我需要防止我的网络应用程序中的水平滚动。我尝试在 touchmove 事件上使用 PreventDefault(),但它也阻止垂直滚动。 有什么想法吗?^^ 我的尝试: $(document)
对于完全适合动画组方法的动画效果,如Brad Larson's answer here所示,我需要动画根据输入进行。特别是触摸和检测到的触摸的位置。处理 TouchMoved: 并为每次触摸设置元素的
我在屏幕上散布了一系列硬币。我想在触摸硬币时添加声音。 private Music coinSound; 在 show() 中: coinSound=assetManager.get(Assets.c
我是一名优秀的程序员,十分优秀!