- 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/
我正在使用 JavaFX 8 创建一个应用程序。我使用拖/放动态更改网格 Pane 的内容。我希望每行或每行/列迭代 GridPane 内容。JavaFX 允许通过指定行和列在 GridPane 中添
我正在尝试将图像拖放到div上。图像没有被拖到div上并给出以下错误 Uncaught TypeError: Failed to execute 'appendChild' on 'Node': pa
我正在 android studio 中创建内部构建 AR 导航。我正在寻找一种方法将 anchor 与其他 anchor 或 anchor 节点/节点“连接”起来。我不确定使用哪一个。基于我将强制用
我在 Hive 上运行一些作业:首先是 4 节点,然后是 2 节点。令我惊讶的是,我的 2 节点性能比我的 4 节点更好。 首先,我在一个 4 节点(4 个事件节点)上运行查询,然后关闭 2 个节点(
我有 Node* current ,我在其中存储指向列表“顶部”当前节点的指针。当我将一个新节点设置为当前节点时,出现错误: '=' : cannot convert from 'CircularDo
我是 dcos Mesos 的新手,在本地 Ubuntu 机器上安装了 dc os。 我可以查看 dcos 仪表板。 但我无法使用 dcos node ssh --master-proxy --lea
在 JavaFX 中,是否有类似 setLayout(); 的东西?或 setBounds(); ? 例如,我想将按钮定位到我想要的位置。 最佳答案 JavaFX 场景图上的所有内容都是 Node .
我正在开发一个 JavaFX 应用程序,其中我开发的类(从 javafx.scene.Parent 扩展)是根据用户在 ListView 控件中单击的条目动态创建的。 只是要清楚这个节点,它不是使用像
我正在尝试为节点-边缘关系创建一个类图,因为它可以在有向图中找到。我想传达的是,Nodes 引用了 Edges,Edges 也引用了 Nodes。每个 Edge 都恰好需要两个 Node(源和目标)。
在mapreduce作业期间,单个任务将在随机节点上运行,是否有任何方法限制应在其中运行任务的节点? 最佳答案 Hadoop不会选择节点来随机运行任务。考虑到数据局部性,否则将有很多网络开销。 任务与
有什么区别: a) nodetool 重建 b) nodetool 修复 [-pr] 换句话来说,各个命令到底是做什么的? 最佳答案 nodetool重建:类似于引导过程(当您向集群添加新节点时),但
我已将第一个 OneToMany 关系添加到我的 hibernate 3.6.10 项目中。这是一个类: /** * */ package com.heavyweightsoftware.leal
是否有可能找到正在监听触发当前函数的事件的元素? 在下面的代码中,event.target 返回 #xScrollPane 和 event.currentTarget 和 event 的最低子节点.f
我正在尝试覆盖我数据库中的一些数据。结构很简单,就是: recipes { user_1{ recipe_1{data} recipe_2{data} } user_2{
我使用 setInterval 来运行该函数,但它会多次执行函数 2... 如何在输入中插入一个值后执行函数 第一个输入与其余输入的距离不同 如何在插入 val(tab 选项)后将插入从 1 个输入移
我不知道代码有什么问题,但在 visual studio 中不断收到这些错误消息。 Error 18 error C1903: unable to recover from previous e
我正在尝试从其类中获取 SharePoint 搜索导航节点的对象。 var nodes = $("div.ms-qSuggest-listItem"); 我正在获取节点对象,现在想要获取“_promp
D:\nodeP>node main.js module.js:327 抛出错误; ^ 错误:在 Function.Module 的 Function.Module._resolveFilename
struct node{ int key, prior, cnt, val; node *l, *r; node(){} node(int nkey) : key(nkey),
我有以下代码使用迭代器将项目插入双链表。这就是我们被要求这样做的方式。代码有效,但问题是我有 24 字节的绝对内存泄漏。 NodeIterator insert(NodeIterator & itrP
我是一名优秀的程序员,十分优秀!