I wanted to show a progression for a gold/glitter tile. The top is the original palette of both dark and light gold pieces. Bottom ends with the current rendition of the dark gold piece. It's gonna sparkle and look luxurious. ;)
http://shekarr.com/
Aqua Utopia|海の底で記憶を紡ぐ
h
YOU ARE THE REASON

izzy's playlists!

let's talk about Bridgerton tea, my ask is open

Discoholic 🪩
he wasn't even looking at me and he found me
we're not kids anymore.
Game of Thrones Daily
Stranger Things

PR's Tumblrdome
almost home

Kiana Khansmith
Sweet Seals For You, Always
$LAYYYTER
Monterey Bay Aquarium

⁂
hello vonnie
I'd rather be in outer space 🛸
seen from United States
seen from Saudi Arabia
seen from Spain

seen from Malaysia

seen from Malaysia

seen from Canada

seen from United States
seen from United States

seen from Malaysia

seen from United States
seen from Argentina

seen from United States
seen from Canada
seen from United States
seen from Germany

seen from United States

seen from United States
seen from United States

seen from Türkiye
seen from Canada
@endersfund
I wanted to show a progression for a gold/glitter tile. The top is the original palette of both dark and light gold pieces. Bottom ends with the current rendition of the dark gold piece. It's gonna sparkle and look luxurious. ;)
http://shekarr.com/

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
BONUS: Here is a rough color block for the "Carnival Casino" map. Wait till you see Anna's amazing fully painted version. Note: No elephants were harmed during the making of this drawing.
More random casino patrons. Although that first guy doesn't look so random...
A rough floor plan sketch for the "Casino del Oro" aka the El Dorado in Reno.
Cocos2d Custom TextField and ComboBox Part 2
I've been expanding our game editor as our project grows and have some revisions to my previous post as well as some new UI elements to share.
TextField
ComboBox
MultiComboBox
List
CountList
DialogueList
Again, the UI elements posted here where made for our internal use only so I apologize before hand if they're a little rough.
Previous post: http://blog.endersfund.com/post/92362574071/cocos2d-custom-textfield-and-combobox
TextField
Description:
Please see previous post.
Usage:
// instantiation PTEditorTextField *textField = [PTEditorTextField textFieldWithTitle:@"My String"]; textField.delegate = self; textField.position = CGPointMake(x, y); [containerNode addChild:textField]; _textField = textField; // setting _textField.stringValue = @"Hello World"; _textField.integerValue = 100; _textField.floatValue = 3.33f; _textField.doubleValue = 10.25; // getting NSString *string = _textField.stringValue; NSInteger integer = _textField.integerValue; CGFloat float = _textField.floatValue; double dbl = _textField.doubleValue
Source:
#import "EFCCBaseNode.h" @class PTEditorTextField; @class CCButton; @class CCTextField; @protocol PTEditorTextFieldDelegate <NSObject> - (void)textFieldWasEdited:(PTEditorTextField *)sender; @end @interface PTEditorTextField : EFCCBaseNode @property (weak, nonatomic) CCLabelTTF *label; @property (weak, nonatomic) CCNodeColor *buttonBackgroundNode; @property (weak, nonatomic) CCButton *button; @property (weak, nonatomic) CCTextField *textField; @property (weak, nonatomic) id <PTEditorTextFieldDelegate> delegate; @property (strong, nonatomic) NSString *title; @property (strong, nonatomic) NSString *stringValue; @property (nonatomic) NSInteger integerValue; @property (nonatomic) CGFloat floatValue; @property (nonatomic) double doubleValue; @property (nonatomic) BOOL enabled; @property (nonatomic) BOOL changed; + (id)textFieldWithTitle:(NSString *)title; @end
#import "PTEditorTextField.h" #import "cocos2d-ui.h" @implementation PTEditorTextField + (id)textFieldWithTitle:(NSString *)title { PTEditorTextField *textField = [self node]; textField.title = title; return textField; } - (void)setEnabled:(BOOL)enabled { if (_enabled != enabled) { _enabled = enabled; _button.enabled = _enabled; _buttonBackgroundNode.color = _enabled ? [CCColor lightGrayColor] : [CCColor darkGrayColor]; _textField.enabled = _enabled; } } #pragma mark - Title - (void)setTitle:(NSString *)title { if (_title != title) { _title = title; _label.string = _title; } } #pragma mark - Button - (void)refreshButton { NSString *title = _textField.string; _button.title = title ? title : @""; _button.preferredSize = _button.title.length > 0 ? CGSizeMake(0.0f, _button.maxSize.height) : _button.maxSize; } #pragma mark - Values - (void)setStringValue:(NSString *)stringValue { _textField.string = stringValue; [self refreshButton]; _changed = NO; } - (NSString *)stringValue { return _textField.string; } - (void)setIntegerValue:(NSInteger)integerValue { _textField.string = [NSString stringWithFormat:@"%d", integerValue]; [self refreshButton]; _changed = NO; } - (NSInteger)integerValue { return [_textField.string integerValue]; } - (void)setFloatValue:(CGFloat)floatValue { _textField.string = [NSString stringWithFormat:@"%.02f", floatValue]; [self refreshButton]; _changed = NO; } - (CGFloat)floatValue { return [_textField.string floatValue]; } - (void)setDoubleValue:(double)doubleValue { [self setFloatValue:doubleValue]; } - (double)doubleValue { return [self floatValue]; } #pragma mark - Update - (void)update:(CCTime)delta { if (_visible && !_button.visible && !_textField.textField.isFirstResponder) { _button.visible = YES; _textField.visible = NO; _changed |= !((_button.title.length == 0 && _textField.string.length == 0) || [_button.title isEqualToString:_textField.string]); // update before delegate call [self refreshButton]; [_delegate textFieldWasEdited:self]; } } #pragma mark - Button Presses - (void)buttonPressed { if (_button.visible && _enabled) { _button.visible = NO; _textField.visible = YES; [_textField.textField becomeFirstResponder]; } } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = CGSizeMake(130.0f, 45.0f); } - (void)setContentSize:(CGSize)contentSize { [super setContentSize:contentSize]; _label.contentSize = CGSizeMake(contentSize.width, _label.contentSize.height); _buttonBackgroundNode.contentSize = CGSizeMake(contentSize.width, _buttonBackgroundNode.contentSize.height); _button.maxSize = CGSizeMake(contentSize.width, _button.contentSize.height); _button.position = CGPointMake(contentSize.width / 2.0f, _button.position.y); _textField.preferredSize = CGSizeMake(contentSize.width, _textField.contentSize.height); [self refreshButton]; } #pragma mark - Data - (void)initializeData { [super initializeData]; _enabled = YES; } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachLabel]; [self attachButton]; [self attachTextField]; } #pragma mark - Label layout - (void)attachLabel { CCLabelTTF *label = [CCLabelTTF labelWithString:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:12.0f dimensions:CGSizeMake(self.contentSize.width, 20.0f)]; label.fontColor = [CCColor blackColor]; label.verticalAlignment = CCVerticalTextAlignmentCenter; label.adjustsFontSizeToFit = YES; label.position = CGPointMake(0.0f, 25.0f); label.anchorPoint = CGPointZero; [self addChild:label]; _label = label; } #pragma mark - Button layout - (void)attachButton { CGSize size = CGSizeMake(self.contentSize.width, 25.0f); CCNodeColor *node = [CCNodeColor nodeWithColor:[CCColor lightGrayColor] width:size.width height:size.height]; [self addChild:node]; _buttonBackgroundNode = node; CCButton *button = [CCButton buttonWithTitle:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f]; [button setTarget:self selector:@selector(buttonPressed)]; [button setLabelColor:[CCColor blackColor] forState:CCControlStateNormal]; button.maxSize = size; button.position = CGPointMake(size.width / 2.0f, size.height / 2.0f); [self addChild:button]; _button = button; [self refreshButton]; } #pragma mark - TextField layout - (void)attachTextField { CGSize size = CGSizeMake(self.contentSize.width, 25.0f); CCTextField *textField = [[CCTextField alloc] init]; textField.preferredSize = size; textField.fontSize = 14.0f; textField.anchorPoint = CGPointZero; [self addChild:textField]; _textField = textField; _textField.visible = NO; } @end
ComboBox
Description:
Please see previous post.
Usage:
//Instantiation PTEditorComboBox *comboBox = [PTEditorComboBox comboBoxWithTitle:@"My Option" options:[NSArray arrayWithObjects:@"Option 1", @"Option 2", @"Option 3", @"Option 4", nil]]; comboBox.delegate = self; comboBox.position = CGPointMake(x, y); [containerNode addChild:comboBox]; _comboBox = comboBox; // Setting _comboBox.value = 3; // option index // Getting NSInteger optionIndex = _comboBox.value;
Source:
#import "EFCCBaseNode.h" #pragma mark - PTEditorComboBoxDelegate @class PTEditorComboBox; @protocol PTEditorComboBoxDelegate <NSObject> - (void)comboBoxWasEdited:(PTEditorComboBox *)sender; @end #pragma mark - PTEditorComboBoxPopupNodeDelegate @protocol PTEditorComboBoxPopupNodeDelegate <NSObject> - (void)comboBoxPopupNodeClosedWithValue:(NSInteger)value; @end #pragma mark - PTEditorComboBox @class PTEditorComboBoxPopupNode; @class CCButton; @interface PTEditorComboBox : EFCCBaseNode <PTEditorComboBoxPopupNodeDelegate> { PTEditorComboBoxPopupNode *_popupNode; NSInteger _value; } @property (weak, nonatomic) CCLabelTTF *label; @property (weak, nonatomic) CCButton *button; @property (weak, nonatomic) CCNodeColor *buttonBackgroundNode; @property (weak, nonatomic) id <PTEditorComboBoxDelegate> delegate; @property (strong, nonatomic) NSString *title; @property (strong, nonatomic) NSArray *options; @property (nonatomic) NSInteger value; @property (nonatomic) BOOL enabled; @property (nonatomic) BOOL changed; + (id)comboBoxWithTitle:(NSString *)title options:(NSArray *)options; #pragma mark - Value - (void)refreshButton; #pragma mark - Popup Node - (void)showPopupNode; @end #pragma mark - PTEditorComboBoxPopupNode #import "EFCCTrackerNode.h" #import "EFCCInertiaScroller.h" @interface PTEditorComboBoxPopupNode : EFCCBaseNode <EFCCTrackerNodeDelegate, EFCCInertiaScrollerDelegate> { NSInteger _value; } @property (weak, nonatomic) EFCCTrackerNode *trackerNode; @property (weak, nonatomic) CCClippingNode *clippingNode; @property (weak, nonatomic) CCNode *toolbarNode; @property (weak, nonatomic) CCNode *containerNode; @property (weak, nonatomic) id <PTEditorComboBoxPopupNodeDelegate> delegate; @property (strong, nonatomic) NSArray *buttons; @property (strong, nonatomic) NSArray *buttonBackgroundNodes; + (id)popupNodeWithTitle:(NSString *)title options:(NSArray *)options andValue:(NSInteger)value; #pragma mark - Close - (void)close; #pragma mark - Buttons - (void)selectOptionValue:(NSInteger)value; - (void)updateButtons; #pragma mark - Toolbar Node layout - (void)attachToolbarNode; @end
#import "PTEditorComboBox.h" #import "cocos2d-ui.h" @implementation PTEditorComboBox + (id)comboBoxWithTitle:(NSString *)title options:(NSArray *)options { PTEditorComboBox *comboBox = [self node]; comboBox.title = title; comboBox.options = options; return comboBox; } - (void)setEnabled:(BOOL)enabled { if (_enabled != enabled) { _enabled = enabled; _button.enabled = _enabled; _buttonBackgroundNode.color = _enabled ? [CCColor lightGrayColor] : [CCColor darkGrayColor]; } } #pragma mark - Title - (void)setTitle:(NSString *)title { if (_title != title) { _title = title; _label.string = _title; } } #pragma mark - Button - (void)refreshButton { NSString *title = nil; if (_value < _options.count) { title = [_options objectAtIndex:_value]; } _button.title = title ? title : @""; _button.preferredSize = _button.title.length > 0 ? CGSizeMake(0.0f, _button.maxSize.height) : _button.maxSize; } #pragma mark - Options - (void)setOptions:(NSArray *)options { if (_options != options) { _options = options; self.value = 0; } } #pragma mark - Value - (void)setValue:(NSInteger)value { if (_value != value) { _value = value; [self refreshButton]; _changed = NO; } } #pragma mark - Popup Node - (void)showPopupNode { if (_popupNode == nil) { PTEditorComboBoxPopupNode *popupNode = [PTEditorComboBoxPopupNode popupNodeWithTitle:_title options:_options andValue:_value]; popupNode.delegate = self; [[CCDirector sharedDirector].runningScene addChild:popupNode]; _popupNode = popupNode; } } #pragma mark - Button Presses - (void)buttonPressed { [self showPopupNode]; } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = CGSizeMake(130.0f, 45.0f); } - (void)setContentSize:(CGSize)contentSize { [super setContentSize:contentSize]; _label.contentSize = CGSizeMake(contentSize.width, _label.contentSize.height); _buttonBackgroundNode.contentSize = CGSizeMake(contentSize.width, _buttonBackgroundNode.contentSize.height); _button.maxSize = CGSizeMake(contentSize.width, _button.contentSize.height); _button.position = CGPointMake(contentSize.width / 2.0f, _button.position.y); [self refreshButton]; } #pragma mark - Data - (void)initializeData { [super initializeData]; _value = -1; _enabled = YES; } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachLabel]; [self attachButton]; } #pragma mark - Label layout - (void)attachLabel { CCLabelTTF *label = [CCLabelTTF labelWithString:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:12.0f dimensions:CGSizeMake(self.contentSize.width, 20.0f)]; label.fontColor = [CCColor blackColor]; label.verticalAlignment = CCVerticalTextAlignmentCenter; label.adjustsFontSizeToFit = YES; label.position = CGPointMake(0.0f, 25.0f); label.anchorPoint = CGPointZero; [self addChild:label]; _label = label; } #pragma mark - Button layout - (void)attachButton { CGSize size = CGSizeMake(self.contentSize.width, 25.0f); CCNodeColor *node = [CCNodeColor nodeWithColor:[CCColor lightGrayColor] width:size.width height:size.height]; [self addChild:node]; _buttonBackgroundNode = node; CCButton *button = [CCButton buttonWithTitle:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f]; [button setTarget:self selector:@selector(buttonPressed)]; [button setLabelColor:[CCColor blackColor] forState:CCControlStateNormal]; button.maxSize = size; button.position = CGPointMake(size.width / 2.0f, size.height / 2.0f); button.anchorPoint = CGPointMake(0.5f, 0.5f); [self addChild:button]; _button = button; [self refreshButton]; } #pragma mark - PTEditorListPopupNodeDelegate - (void)comboBoxPopupNodeClosedWithValue:(NSInteger)value { _popupNode = nil; // update value _changed |= _value != value; // update before delegate call _value = value; [self refreshButton]; [_delegate comboBoxWasEdited:self]; } @end #pragma mark - PTEditorComboBoxPopupNode @implementation PTEditorComboBoxPopupNode { EFCCInertiaScroller *_inertiaScroller; CGRect _scrollRect; NSString *_title; NSArray *_options; } + (id)popupNodeWithTitle:(NSString *)title options:(NSArray *)options andValue:(NSInteger)value { return [[self alloc] initWithTitle:title options:options andValue:value]; } - (id)initWithTitle:(NSString *)title options:(NSArray *)options andValue:(NSInteger)value { _title = title; _options = options; _value = value; self = [self init]; if (self) { } return self; } #pragma mark - Close - (void)close { [self removeFromParentAndCleanup:YES]; [_delegate comboBoxPopupNodeClosedWithValue:_value]; } #pragma mark - Buttons - (void)selectOptionValue:(NSInteger)value { _value = value; [self close]; } - (void)updateButtons { NSInteger value = 0; for (CCButton *button in _buttons) { CCNodeColor *backgroundNode = [_buttonBackgroundNodes objectAtIndex:value]; backgroundNode.color = _value == value || button.highlighted ? [CCColor redColor] : [CCColor lightGrayColor]; // iterate value++; } } #pragma mark - Update - (void)update:(CCTime)delta { [_inertiaScroller update:delta]; [self updateButtons]; } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = [[CCDirector sharedDirector] viewSize]; } #pragma mark - Data - (void)initializeData { [super initializeData]; self.userInteractionEnabled = YES; self.terminateTouches = YES; self.zOrder = 999; } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachTrackerNode]; [self attachScreenNode]; [self attachClippingNode]; [self attachToolbarNode]; [self attachContainerNode]; } #pragma mark - Tracker Node layout - (void)attachTrackerNode { EFCCTrackerNode *trackerNode = [EFCCTrackerNode node]; trackerNode.delegate = self; trackerNode.contentSize = self.contentSize; [self addChild:trackerNode]; _trackerNode = trackerNode; } #pragma mark - Screen Node layout - (void)attachScreenNode { CGSize size = self.contentSize; CCNodeColor *screenNode = [CCNodeColor nodeWithColor:[CCColor colorWithWhite:0.0f alpha:0.6f] width:size.width height:size.height]; [self addChild:screenNode]; } #pragma mark - Clipping Node layout - (void)attachClippingNode { CGSize size = CGSizeMake(240.0f, 320.0f); CCNodeColor *stencilNode = [CCNodeColor nodeWithColor:[CCColor blackColor] width:size.width height:size.height]; stencilNode.contentSize = size; CCClippingNode *clippingNode = [CCClippingNode clippingNodeWithStencil:stencilNode]; clippingNode.contentSize = size; clippingNode.positionType = CCPositionTypeNormalized; clippingNode.position = CGPointMake(0.5f, 0.5f); clippingNode.anchorPoint = CGPointMake(0.5f, 0.5f); [self addChild:clippingNode]; _clippingNode = clippingNode; CCNodeColor *backgroundNode = [CCNodeColor nodeWithColor:[CCColor whiteColor]]; backgroundNode.contentSize = size; [_clippingNode addChild:backgroundNode]; } #pragma mark - Toolbar Node layout - (void)attachToolbarNode { CGSize parentSize = _clippingNode.contentSize; CGSize size = CGSizeMake(parentSize.width, 30.0f); CCNodeColor *toolbarNode = [CCNodeColor nodeWithColor:[CCColor redColor] width:size.width height:size.height]; toolbarNode.position = CGPointMake(0.0f, parentSize.height - size.height); toolbarNode.zOrder = 1; [_clippingNode addChild:toolbarNode]; _toolbarNode = toolbarNode; CCLabelTTF *label = [CCLabelTTF labelWithString:_title fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f dimensions:size]; label.horizontalAlignment = CCTextAlignmentCenter; label.verticalAlignment = CCVerticalTextAlignmentCenter; label.anchorPoint = CGPointZero; [_toolbarNode addChild:label]; } #pragma mark - Container Node layout - (void)attachContainerNode { CCNode *containerNode = [CCNode node]; [_clippingNode addChild:containerNode]; _containerNode = containerNode; NSMutableArray *buttons = [NSMutableArray array]; NSMutableArray *buttonBackgroundNodes = [NSMutableArray array]; CGSize clippingNodeSize = _clippingNode.contentSize; CGSize parentSize = CGSizeMake(clippingNodeSize.width, clippingNodeSize.height - _toolbarNode.boundingBox.size.height); CGSize buttonSize = CGSizeMake(180.0f, 25.0f); CGFloat padding = 20.0f; CGFloat margin = 10.0f; CGSize size = CGSizeMake(parentSize.width, MAX(parentSize.height, _options.count * (buttonSize.height + margin) + 2.0f * padding)); CGFloat x = (size.width - buttonSize.width) / 2.0f; CGFloat y = size.height - buttonSize.height - padding; NSInteger value = 0; for (NSString *option in _options) { CCNodeColor *buttonBackgroundNode = [CCNodeColor nodeWithColor:[CCColor lightGrayColor] width:buttonSize.width height:buttonSize.height]; buttonBackgroundNode.position = CGPointMake(x, y); [_containerNode addChild:buttonBackgroundNode]; [buttonBackgroundNodes addObject:buttonBackgroundNode]; CCButton *button = [CCButton buttonWithTitle:option fontName:EF_DEFAULT_FONT_NAME fontSize:12.0f]; __weak PTEditorComboBoxPopupNode *weakSelf = self; [button setBlock:^(id sender) { [weakSelf selectOptionValue:value]; }]; [button setLabelColor:[CCColor blackColor] forState:CCControlStateNormal]; button.maxSize = buttonSize; button.preferredSize = button.title.length > 0 ? CGSizeMake(0.0f, button.maxSize.height) : button.maxSize; button.position = CGPointMake(x + buttonSize.width / 2.0f, y + buttonSize.height / 2.0f); button.anchorPoint = CGPointMake(0.5f, 0.5f); [_containerNode addChild:button]; [buttons addObject:button]; // iterate value++; y -= buttonSize.height + margin; } _buttons = buttons; _buttonBackgroundNodes = buttonBackgroundNodes; // initial position _containerNode.position = CGPointMake(0.0f, parentSize.height - size.height); // scroller _scrollRect = CGRectMake(0.0f, _containerNode.position.y, 0.0f, size.height - parentSize.height); _inertiaScroller = [[EFCCInertiaScroller alloc] initWithScrollX:NO scrollY:YES bounds:_scrollRect delegate:self]; } #pragma mark - EFCCTrackerNodeDelegate - (void)trackerNodeTouch:(UITouch *)touch downAtPoint:(CGPoint)point { [_inertiaScroller touch:touch downAtPoint:point]; } - (void)trackerNodeTouch:(UITouch *)touch movedAtPoint:(CGPoint)point { [_inertiaScroller touch:touch movedAtPoint:point]; } - (void)trackerNodeTouch:(UITouch *)touch upAtPoint:(CGPoint)point { [_inertiaScroller touch:touch upAtPoint:point]; } #pragma mark - EFCCInertiaScrollerDelegate - (CGPoint)inertiaScrollerPosition:(EFCCInertiaScroller *)inertiaScroller { return _containerNode.position; } - (void)inertiaScroller:(EFCCInertiaScroller *)inertiaScroller setPosition:(CGPoint)position { _containerNode.position = position; } @end
MultiComboBox
Description:
The MultiComboBox is a subclass of ComboBox. It allows for multiple items to be selected and returns a bitmask where the option i corresponds to the 1 << i bit. Typically, you would create an enum of the different bit mask values.
Usage:
// instantiation PTEditorMultiComboBox *multiComboBox = [PTEditorMultiComboBox comboBoxWithTitle:@"My Options" options:[NSArray arrayWithObjects:@"Option 1", @"Option 2", @"Option 3", @"Option 4", @"Option 5", nil]]; multiComboBox.delegate = self; multiComboBox.position = CGPointMake(x, y); [containerNode addChild:multiComboBox]; _multiComboBox = multiComboBox; // setting NSInteger values = 0; values |= 1 << 0; // enable Option 1 value |= 1 << 3; // enable Option 4; _multiComboBox.value = value; // getting NSInteger values = _multiComboBox.value; if (values | 1 << 3) { // is Option 4 enabled? // do something }
Source:
#import "PTEditorComboBox.h" @interface PTEditorMultiComboBox : PTEditorComboBox @end #pragma mark - PTEditorMultiComboBoxPopupNode @interface PTEditorMultiComboBoxPopupNode : PTEditorComboBoxPopupNode @end
#import "PTEditorMultiComboBox.h" #import "cocos2d-ui.h" @implementation PTEditorMultiComboBox #pragma mark - Value - (void)refreshButton { NSString *title = nil; NSArray *options = self.options; if (_value == 0) { title = [options objectAtIndex:0]; } else { NSMutableString *string = [NSMutableString string]; NSInteger value = -1; for (NSString *option in options) { if (value >= 0 && _value & 1 << value) { if (string.length > 0) { [string appendString:@"|"]; } [string appendString:option]; } // iterate value++; } title = string; } [self.button setTitle:title]; } #pragma mark - Popup Node - (void)showPopupNode { if (_popupNode == nil) { PTEditorMultiComboBoxPopupNode *popupNode = [PTEditorMultiComboBoxPopupNode popupNodeWithTitle:self.title options:self.options andValue:_value]; popupNode.delegate = self; [[CCDirector sharedDirector].runningScene addChild:popupNode]; _popupNode = popupNode; } } @end #pragma mark - PTEditorMultiComboBoxPopupNode @implementation PTEditorMultiComboBoxPopupNode #pragma mark - Buttons - (void)selectOptionValue:(NSInteger)value { value--; // update value NSInteger bitMask = _value; if (value == -1) { bitMask = 0; } else { bitMask ^= 1 << value; } _value = bitMask; } - (void)updateButtons { NSInteger i = 0; NSArray *buttonBackgroundNodes = self.buttonBackgroundNodes; for (CCButton *button in self.buttons) { NSInteger value = i - 1; CCNodeColor *backgroundNode = [buttonBackgroundNodes objectAtIndex:i]; backgroundNode.color = (value == -1 && _value == 0) || (value >= -1 && _value & 1 << value) || button.highlighted ? [CCColor redColor] : [CCColor lightGrayColor]; // iterate i++; } } #pragma mark - Button Presses - (void)closeButtonPressed { [self close]; } #pragma mark - Toolbar Node layout - (void)attachToolbarNode { [super attachToolbarNode]; CCButton *closeButton = [CCButton buttonWithTitle:@"[X]" fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f]; [closeButton setTarget:self selector:@selector(closeButtonPressed)]; CGSize size = self.toolbarNode.contentSize; CGSize buttonSize = closeButton.boundingBox.size; closeButton.position = CGPointMake(size.width - buttonSize.width / 2.0f - 5.0f, size.height - buttonSize.height / 2.0f - 5.0f); [self.toolbarNode addChild:closeButton]; } @end
List
Description:
The List element is an entirely new UI element I created. It allows for variable length array inputs. You can subclass this baseclass to create a list of multiple item types, even complex types like dictionaries. The base class here supports TextFields and returns an array of strings.
Usage:
// instantiation PTEditorList *list = [PTEditorList listWithTitle:@"String List"]; list.delegate = self; list.position = CGPointMake(x, y); [containerNode addChild:list]; _list = list; // setting _list.items = [NSArray arrayWithObjects:@"Item 1", @"Item 2", @"Item 3", nil]; // getting NSArray *items = _list.items;
Source:
#import "EFCCBaseNode.h" #pragma mark - PTEditorListDelegate @class PTEditorList; @protocol PTEditorListDelegate <NSObject> - (void)listWasEdited:(PTEditorList *)sender; @end #pragma mark - PTEditorListPopupNodeDelegate @protocol PTEditorListPopupNodeDelegate <NSObject> - (void)listPopupNodeDidCloseWithItems:(NSArray *)items; @end #pragma mark - PTEditorListInputNode @protocol PTEditorListInputNode <NSObject> - (id)item; - (void)setItem:(id)item; - (BOOL)isEmpty; // CCNode - (void)removeFromParent; - (void)removeFromParentAndCleanup:(BOOL)cleanup; @end #pragma mark - PTEditorList @class PTEditorListPopupNode; @class CCButton; @interface PTEditorList : EFCCBaseNode <PTEditorListPopupNodeDelegate> { PTEditorListPopupNode *_popupNode; } @property (weak, nonatomic) CCLabelTTF *label; @property (weak, nonatomic) CCButton *button; @property (weak, nonatomic) CCNodeColor *buttonBackgroundNode; @property (weak, nonatomic) id <PTEditorListDelegate> delegate; @property (strong, nonatomic) NSString *title; @property (strong, nonatomic) NSArray *items; @property (nonatomic) BOOL enabled; @property (nonatomic) BOOL changed; + (id)listWithTitle:(NSString *)title; #pragma mark - Popup Node - (void)showPopupNode; @end #pragma mark - PTEditorListPopupNode #import "PTEditorTextField.h" #import "EFCCTrackerNode.h" #import "EFCCInertiaScroller.h" @interface PTEditorListPopupNode : EFCCBaseNode <PTEditorTextFieldDelegate, EFCCTrackerNodeDelegate, EFCCInertiaScrollerDelegate> @property (weak, nonatomic) EFCCTrackerNode *trackerNode; @property (weak, nonatomic) CCClippingNode *clippingNode; @property (weak, nonatomic) CCNode *toolbarNode; @property (weak, nonatomic) CCNode *containerNode; @property (weak, nonatomic) id <PTEditorListPopupNodeDelegate> delegate; @property (strong, nonatomic) NSMutableArray *inputNodes; + (id)popupNodeWithTitle:(NSString *)title items:(NSArray *)items; - (id)initWithTitle:(NSString *)title items:(NSArray *)items; #pragma mark - Input Nodes - (id <PTEditorListInputNode>)generateInputNode:(NSInteger)index; - (CGFloat)inputNodeHeight; - (void)inputNodeWasEdited:(id <PTEditorListInputNode>)sender; @end #pragma mark - PTEditorListInputTextFieldNode @interface PTEditorListInputTextFieldNode : PTEditorTextField <PTEditorListInputNode> @end
#import "PTEditorList.h" #import "cocos2d-ui.h" @implementation PTEditorList + (id)listWithTitle:(NSString *)title { PTEditorList *list = [self node]; list.title = title; return list; } - (void)setEnabled:(BOOL)enabled { if (_enabled != enabled) { _enabled = enabled; _button.enabled = _enabled; _buttonBackgroundNode.color = _enabled ? [CCColor lightGrayColor] : [CCColor darkGrayColor]; } } #pragma mark - Title - (void)setTitle:(NSString *)title { if (_title != title) { _title = title; _label.string = _title; } } #pragma mark - Button - (void)refreshButton { NSString *title = [NSString stringWithFormat:@"%d", _items.count]; _button.title = title ? title : @""; _button.preferredSize = _button.title.length > 0 ? CGSizeMake(0.0f, _button.maxSize.height) : _button.maxSize; } #pragma mark - Items - (void)setItems:(NSArray *)items { if (_items != items) { _items = items; [self refreshButton]; _changed = NO; } } #pragma mark - Popup Node - (void)showPopupNode { if (_popupNode == nil) { PTEditorListPopupNode *popupNode = [PTEditorListPopupNode popupNodeWithTitle:_title items:_items]; popupNode.delegate = self; [[CCDirector sharedDirector].runningScene addChild:popupNode]; _popupNode = popupNode; } } #pragma mark - Button Presses - (void)buttonPressed { [self showPopupNode]; } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = CGSizeMake(130.0f, 45.0f); } - (void)setContentSize:(CGSize)contentSize { [super setContentSize:contentSize]; _label.contentSize = CGSizeMake(contentSize.width, _label.contentSize.height); _buttonBackgroundNode.contentSize = CGSizeMake(contentSize.width, _buttonBackgroundNode.contentSize.height); _button.maxSize = CGSizeMake(contentSize.width, _button.contentSize.height); _button.position = CGPointMake(contentSize.width / 2.0f, _button.position.y); [self refreshButton]; } #pragma mark - Data - (void)initializeData { [super initializeData]; _items = [NSMutableArray array]; _enabled = YES; } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachLabel]; [self attachButton]; } #pragma mark - Label layout - (void)attachLabel { CCLabelTTF *label = [CCLabelTTF labelWithString:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:12.0f dimensions:CGSizeMake(self.contentSize.width, 20.0f)]; label.fontColor = [CCColor blackColor]; label.verticalAlignment = CCVerticalTextAlignmentCenter; label.adjustsFontSizeToFit = YES; label.position = CGPointMake(0.0f, 25.0f); label.anchorPoint = CGPointZero; [self addChild:label]; _label = label; } #pragma mark - Button layout - (void)attachButton { CGSize size = CGSizeMake(self.contentSize.width, 25.0f); CCNodeColor *node = [CCNodeColor nodeWithColor:[CCColor lightGrayColor] width:size.width height:size.height]; [self addChild:node]; _buttonBackgroundNode = node; CCButton *button = [CCButton buttonWithTitle:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f]; [button setTarget:self selector:@selector(buttonPressed)]; [button setLabelColor:[CCColor blackColor] forState:CCControlStateNormal]; button.maxSize = size; button.position = CGPointMake(size.width / 2.0f, size.height / 2.0f); button.anchorPoint = CGPointMake(0.5f, 0.5f); [self addChild:button]; _button = button; [self refreshButton]; } #pragma mark - PTEditorListPopupNodeDelegate - (void)listPopupNodeDidCloseWithItems:(NSArray *)items { _popupNode = nil; // update value _changed |= ![_items isEqualToArray:items]; _items = items; [self refreshButton]; [_delegate listWasEdited:self]; } @end #pragma mark - PTEditorListPopupNode @implementation PTEditorListPopupNode { EFCCInertiaScroller *_inertiaScroller; CGRect _scrollRect; NSString *_title; NSArray *_items; } + (id)popupNodeWithTitle:(NSString *)title items:(NSArray *)items { return [[self alloc] initWithTitle:title items:items]; } - (id)initWithTitle:(NSString *)title items:(NSArray *)items { _title = title; _items = items; self = [self init]; if (self) { } return self; } #pragma mark - Close - (void)close { [self removeFromParentAndCleanup:YES]; NSMutableArray *items = [NSMutableArray array]; for (id <PTEditorListInputNode> inputNode in _inputNodes) { if (![inputNode isEmpty]) { [items addObject:[inputNode item]]; } } [_delegate listPopupNodeDidCloseWithItems:items]; } #pragma mark - Input Nodes - (id <PTEditorListInputNode>)generateInputNode:(NSInteger)index { return [self generateTextField:index]; } - (CGFloat)inputNodeHeight { return [self textFieldHeight]; } - (void)inputNodeWasEdited:(id <PTEditorListInputNode>)sender { NSInteger count = _inputNodes.count; id <PTEditorListInputNode> lastInputNode = [_inputNodes lastObject]; if (sender == lastInputNode) { if (![sender isEmpty]) { [self generateInputNode:count]; [self refreshScroller]; } } else if (count > 1 && sender == [_inputNodes objectAtIndex:count - 2] && [sender isEmpty]) { [lastInputNode removeFromParentAndCleanup:YES]; [_inputNodes removeLastObject]; [self refreshScroller]; } } #pragma mark - Text Fields - (PTEditorListInputTextFieldNode *)generateTextField:(NSInteger)index { PTEditorListInputTextFieldNode *textField = [PTEditorListInputTextFieldNode textFieldWithTitle:[NSString stringWithFormat:@"%d", index + 1]]; textField.delegate = self; textField.contentSize = CGSizeMake(200.0f, textField.contentSize.height); textField.position = CGPointMake(20.0f, -[self inputNodeHeight] * (index + 1)); [_containerNode addChild:textField]; [_inputNodes addObject:textField]; return textField; } - (CGFloat)textFieldHeight { return 50.0f; } #pragma mark - Scrolling - (void)refreshScroller { CGFloat parentHeight = _containerNode.contentSize.height - _toolbarNode.boundingBox.size.height; CGFloat height = MAX(_inputNodes.count * [self inputNodeHeight] + 10.0f - parentHeight, 0.0f); _scrollRect = CGRectMake(0.0f, _toolbarNode.position.y, 0.0f, height); _inertiaScroller = [[EFCCInertiaScroller alloc] initWithScrollX:NO scrollY:YES bounds:_scrollRect delegate:self]; } #pragma mark - Update - (void)update:(CCTime)delta { [_inertiaScroller update:delta]; } #pragma mark - Button Presses - (void)closeButtonPressed { [self close]; } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = [[CCDirector sharedDirector] viewSize]; } #pragma mark - Data - (void)initializeData { [super initializeData]; self.userInteractionEnabled = YES; self.terminateTouches = YES; self.zOrder = 999; _inputNodes = [NSMutableArray array]; } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachTrackerNode]; [self attachScreenNode]; [self attachClippingNode]; [self attachToolbarNode]; [self attachContainerNode]; } #pragma mark - Tracker Node layout - (void)attachTrackerNode { EFCCTrackerNode *trackerNode = [EFCCTrackerNode node]; trackerNode.delegate = self; trackerNode.contentSize = self.contentSize; [self addChild:trackerNode]; _trackerNode = trackerNode; } #pragma mark - Screen Node layout - (void)attachScreenNode { CGSize size = self.contentSize; CCNodeColor *screenNode = [CCNodeColor nodeWithColor:[CCColor colorWithWhite:0.0f alpha:0.6f] width:size.width height:size.height]; [self addChild:screenNode]; } #pragma mark - Clipping Node layout - (void)attachClippingNode { CGSize size = CGSizeMake(240.0f, 320.0f); CCNodeColor *stencilNode = [CCNodeColor nodeWithColor:[CCColor blackColor] width:size.width height:size.height]; stencilNode.contentSize = size; CCClippingNode *clippingNode = [CCClippingNode clippingNodeWithStencil:stencilNode]; clippingNode.contentSize = size; clippingNode.positionType = CCPositionTypeNormalized; clippingNode.position = CGPointMake(0.5f, 0.5f); clippingNode.anchorPoint = CGPointMake(0.5f, 0.5f); [self addChild:clippingNode]; _clippingNode = clippingNode; CCNodeColor *backgroundNode = [CCNodeColor nodeWithColor:[CCColor whiteColor]]; backgroundNode.contentSize = size; [_clippingNode addChild:backgroundNode]; } #pragma mark - Toolbar Node layout - (void)attachToolbarNode { CGSize parentSize = _clippingNode.contentSize; CGSize size = CGSizeMake(parentSize.width, 30.0f); CCNodeColor *toolbarNode = [CCNodeColor nodeWithColor:[CCColor redColor] width:size.width height:size.height]; toolbarNode.position = CGPointMake(0.0f, parentSize.height - size.height); toolbarNode.zOrder = 1; [_clippingNode addChild:toolbarNode]; _toolbarNode = toolbarNode; CCButton *closeButton = [CCButton buttonWithTitle:@"[X]" fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f]; [closeButton setTarget:self selector:@selector(closeButtonPressed)]; CGSize buttonSize = closeButton.boundingBox.size; closeButton.position = CGPointMake(size.width - buttonSize.width / 2.0f - 5.0f, size.height - buttonSize.height / 2.0f - 5.0f); [_toolbarNode addChild:closeButton]; CCLabelTTF *label = [CCLabelTTF labelWithString:_title fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f dimensions:size]; label.horizontalAlignment = CCTextAlignmentCenter; label.verticalAlignment = CCVerticalTextAlignmentCenter; label.anchorPoint = CGPointZero; [_toolbarNode addChild:label]; } #pragma mark - Container Node layout - (void)attachContainerNode { CCNode *containerNode = [CCNode node]; containerNode.position = CGPointMake(0.0f, _toolbarNode.position.y); [_clippingNode addChild:containerNode]; _containerNode = containerNode; NSInteger i = 0; for (id item in _items) { id <PTEditorListInputNode> inputNode = [self generateInputNode:i]; [inputNode setItem:item]; // iterate i++; } [self generateInputNode:i]; [self refreshScroller]; } #pragma mark - PTEditorTextFieldDelegate - (void)textFieldWasEdited:(PTEditorTextField *)sender { [self inputNodeWasEdited:(PTEditorListInputTextFieldNode *)sender]; } #pragma mark - EFCCTrackerNodeDelegate - (void)trackerNodeTouch:(UITouch *)touch downAtPoint:(CGPoint)point { [_inertiaScroller touch:touch downAtPoint:point]; } - (void)trackerNodeTouch:(UITouch *)touch movedAtPoint:(CGPoint)point { [_inertiaScroller touch:touch movedAtPoint:point]; } - (void)trackerNodeTouch:(UITouch *)touch upAtPoint:(CGPoint)point { [_inertiaScroller touch:touch upAtPoint:point]; } #pragma mark - EFCCInertiaScrollerDelegate - (CGPoint)inertiaScrollerPosition:(EFCCInertiaScroller *)inertiaScroller { return _containerNode.position; } - (void)inertiaScroller:(EFCCInertiaScroller *)inertiaScroller setPosition:(CGPoint)position { _containerNode.position = position; } @end #pragma mark - PTEditorListInputTextFieldNode @implementation PTEditorListInputTextFieldNode - (void)setItem:(id)item { self.stringValue = item; } - (id)item { return self.stringValue; } - (BOOL)isEmpty { return self.stringValue.length == 0; } @end
PTEditorCountList
Description:
This is a subclass of the List element. It's our first example of a more complex list. In this case, the list returned is an array of dictionaries that has type and count keys. The first key is set via a ComboBox and the last is set via a TextField.
Usage:
// Instantiation: PTEditorCountList *countList = [PTEditorCountList listWithTitle:@"My List of Types and Counts" options:[NSArray arrayWithObjects:@"Type 1", @"Type 2", @"Type 3", nil]]; countList.delegate = self; countList.position = CGPointMake(x, y); [containerNode addChild:countList]; _list = countList; // Setting: _list.items = [NSArray arrayWithItems:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:3], @"type", [NSNumber numberWithInteger:99], @"count", nil], [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:5], @"type", [NSNumber numberWithInteger:24], @"count", nil], nil]; // Getting: NSArray *items = _list.items;
Source:
#import "PTEditorList.h" @class PTEditorListInputCountNode; @protocol PTEditorListInputCountNodeDelegate <NSObject> - (void)listInputCountNodeWasEdited:(PTEditorListInputCountNode *)sender; @end @interface PTEditorCountList : PTEditorList @property (strong, nonatomic) NSArray *options; + (id)listWithTitle:(NSString *)title options:(NSArray *)options; @end #pragma mark - PTEditorCountListPopupNode @interface PTEditorCountListPopupNode : PTEditorListPopupNode <PTEditorListInputCountNodeDelegate> @property (strong, nonatomic) NSArray *options; + (id)popupNodeWithTitle:(NSString *)title items:(NSArray *)items options:(NSArray *)options; - (id)initWithTitle:(NSString *)title items:(NSArray *)items options:(NSArray *)options; @end #pragma mark - PTEditorListInputCountNode #import "PTEditorComboBox.h" #import "PTEditorTextField.h" @interface PTEditorListInputCountNode : EFCCBaseNode <PTEditorListInputNode, PTEditorComboBoxDelegate, PTEditorTextFieldDelegate> @property (weak, nonatomic) PTEditorComboBox *comboBox; @property (weak, nonatomic) PTEditorTextField *textField; @property (weak, nonatomic) id <PTEditorListInputCountNodeDelegate> delegate; + (id)inputCountIndex:(NSInteger)index options:(NSArray *)options; @end
#import "PTEditorCountList.h" @implementation PTEditorCountList + (id)listWithTitle:(NSString *)title options:(NSArray *)options { PTEditorCountList *list = [self listWithTitle:title]; list.options = options; return list; } #pragma mark - Popup Node - (void)showPopupNode { if (_popupNode == nil) { PTEditorCountListPopupNode *popupNode = [PTEditorCountListPopupNode popupNodeWithTitle:self.title items:self.items options:_options]; popupNode.delegate = self; [[CCDirector sharedDirector].runningScene addChild:popupNode]; _popupNode = popupNode; } } @end #pragma mark - PTEditorCountListPopupNode @implementation PTEditorCountListPopupNode + (id)popupNodeWithTitle:(NSString *)title items:(NSArray *)items options:(NSArray *)options { return [[self alloc] initWithTitle:title items:items options:options]; } - (id)initWithTitle:(NSString *)title items:(NSArray *)items options:(NSArray *)options { _options = options; self = [self initWithTitle:title items:items]; if (self) { } return self; } #pragma mark - Input Nodes - (id <PTEditorListInputNode>)generateInputNode:(NSInteger)index { return [self generateInputCountNode:index]; } - (CGFloat)inputNodeHeight { return [self inputCountNodeHeight]; } #pragma mark - Input Count Nodes - (PTEditorListInputCountNode *)generateInputCountNode:(NSInteger)index { PTEditorListInputCountNode *inputCountNode = [PTEditorListInputCountNode inputCountIndex:index options:_options]; inputCountNode.delegate = self; inputCountNode.position = CGPointMake(20.0f, -[self inputNodeHeight] * (index + 1)); [self.containerNode addChild:inputCountNode]; [self.inputNodes addObject:inputCountNode]; return inputCountNode; } - (CGFloat)inputCountNodeHeight { return 50.0f; } #pragma mark - PTEditorListInputCountNodeDelegate - (void)listInputCountNodeWasEdited:(PTEditorListInputCountNode *)sender { [self inputNodeWasEdited:sender]; } @end #pragma mark - PTEditorListInputCountNode @implementation PTEditorListInputCountNode { NSInteger _index; NSArray *_options; } + (id)inputCountIndex:(NSInteger)index options:(NSArray *)options { return [[self alloc] initWithIndex:index options:options]; } - (id)initWithIndex:(NSInteger)index options:(NSArray *)options { _index = index; _options = options; self = [self init]; if (self) { } return self; } - (void)setItem:(id)item { NSDictionary *dictionary = (NSDictionary *)item; _comboBox.value = [[dictionary objectForKey:@"type"] integerValue]; _textField.integerValue = [[dictionary objectForKey:@"count"] integerValue]; } - (id)item { return [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInteger:_comboBox.value], @"type", [NSNumber numberWithInteger:_textField.integerValue], @"count", nil]; } - (BOOL)isEmpty { return _comboBox.value == 0 && _textField.integerValue == 0; } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = CGSizeMake(200.0f, 45.0f); } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachComboBox]; [self attachTextField]; } #pragma mark - Combo Box layout - (void)attachComboBox { PTEditorComboBox *comboBox = [PTEditorComboBox comboBoxWithTitle:[NSString stringWithFormat:@"%d type", _index + 1] options:_options]; comboBox.delegate = self; comboBox.contentSize = CGSizeMake((self.contentSize.width - 10.0f) / 2.0f, comboBox.contentSize.height); [self addChild:comboBox]; _comboBox = comboBox; } #pragma mark - Text Field layout - (void)attachTextField { PTEditorTextField *textField = [PTEditorTextField textFieldWithTitle:@"count"]; textField.delegate = self; textField.contentSize = CGSizeMake((self.contentSize.width - 10.0f) / 2.0f, textField.contentSize.height); textField.position = CGPointMake(textField.contentSize.width + 10.0f, 0.0f); [self addChild:textField]; _textField = textField; } #pragma mark - PTEditorComboBoxDelegate - (void)comboBoxWasEdited:(PTEditorComboBox *)sender { [_delegate listInputCountNodeWasEdited:self]; } #pragma mark - PTEditorTextFieldDelegate - (void)textFieldWasEdited:(PTEditorTextField *)sender { [_delegate listInputCountNodeWasEdited:self]; } @end
DialogueList
Description:
This subclass of the List element is where things get really interesting. The new game is the first game we've built that has dialogue trees. Depending on how you answer dialogue, the NPC will respond in different ways. The DialogueList element allows us to nest responses and serialize the tree with the help of recursion.
Usage:
// Instantiation PTEditorDialogueList *dialogueList = [PTEditorDialogueList listWithTitle:@"Dialogue" picOptions:_levelDialoguePicBasenames]; dialogueList.delegate = self; dialogueList.listDialogueDelegate = self; dialogueList.position = CGPointMake(x, y); [containerNode addChild:dialogueList]; _list = dialogueList; // Setting & Getting // This is the same as the other examples. Here's a JSON serialization of what to expect: // [{"pic":"Mentor","responses":[{"dialogue":[{"pic":"Mentor","responses":[{"dialogue":[{"pic":"Mentor","responses":[{"dialogue":[{"pic":"Mentor","responses":[{"dialogue":[],"text":"If you only knew..."},{"dialogue":[],"text":""}],"text":"I'm sure you're very well... Equipped to do that."},{"pic":"Mentor","responses":[{"text":"(wink)"},{}],"text":"Is it getting hot in here? Whew... I think I need a cigarette."}],"text":"From my desire to please you."},{"dialogue":[{"pic":"Mentor","responses":[{"dialogue":[],"text":""},{}],"text":"Alright casanova, down boy!"}],"text":"You are my muse."}],"text":"My my, where did you get that silver tongue of yours?"}],"text":"I only speak the truth."},{"dialogue":[{"pic":"Mentor","responses":[{},{}],"text":"Hrmmph!"}],"text":"I was just kidding. Keep your shirt on."}],"text":"You flatter me!"},{"pic":"Mentor","responses":[{},{}],"text":"What were you about to say Larry?"}],"text":"Hi beautiful!"},{"dialogue":[],"text":"Heya..."}],"text":"Hello there!"},{"pic":"Trainer","responses":[{"text":"She has?"},{"text":"I'm not surprised."}],"text":"The mentor has told me a lot about you"},{"pic":"Mentor","responses":[{},{}],"text":"I have?"},{"pic":"Trainer","responses":[{},{}],"text":"Sure you have!"},{"pic":"Mentor","responses":[{"text":"You don't remember me?"},{}],"text":"I think I'd remember if I did."},{"pic":"Trainer","responses":[{"text":"It must have been a while ago."},{"dialogue":[{"pic":"Mentor","responses":[{"dialogue":[],"text":""},{"dialogue":[],"text":""}],"text":"That's not very nice!"},{"pic":"Trainer","responses":[{"dialogue":[],"text":"As you wish..."},{}],"text":"Only I can call her a dumb wench."}],"text":"Yeah! You dumb wench!"}],"text":"You dumb wench you told me about it last time you were here!"},{"pic":"Mentor","responses":[{"text":"*sigh*"},{}],"text":"I came here?"},{"pic":"Trainer","responses":[{"text":"Let's just move on."},{}],"text":"Forget it!"}]
Source:
#import "PTEditorList.h" #pragma mark - PTEditorListInputDialogueNodeDelegate @class PTEditorListInputDialogueNode; @protocol PTEditorListInputDialogueNodeDelegate <NSObject> - (void)listInputDialogueNodeWasEdited:(PTEditorListInputDialogueNode *)sender; @end #pragma mark - PTEditorDialogueListDelegate @class PTEditorDialogueList; @protocol PTEditorDialogueListDelegate <NSObject> - (void)listDialoguePreview:(PTEditorDialogueList *)sender; @end #pragma mark - PTEditorDialogueList @interface PTEditorDialogueList : PTEditorList @property (weak, nonatomic) CCButton *previewButton; @property (weak, nonatomic) id <PTEditorDialogueListDelegate> listDialogueDelegate; @property (strong, nonatomic) NSArray *picOptions; + (id)listWithTitle:(NSString *)title picOptions:(NSArray *)picOptions; @end #pragma mark - PTEditorDialogueListPopupNode @interface PTEditorDialogueListPopupNode : PTEditorListPopupNode <PTEditorListInputDialogueNodeDelegate> @property (strong, nonatomic) NSArray *picOptions; + (id)popupNodeWithTitle:(NSString *)title items:(NSArray *)items picOptions:(NSArray *)picOptions; - (id)initWithTitle:(NSString *)title items:(NSArray *)items picOptions:(NSArray *)picOptions; @end #pragma mark - PTEditorListInputDialogueNode #import "PTEditorComboBox.h" #import "PTEditorTextField.h" @interface PTEditorListInputDialogueNode : EFCCBaseNode <PTEditorListInputNode, PTEditorComboBoxDelegate, PTEditorTextFieldDelegate, PTEditorListDelegate> @property (weak, nonatomic) PTEditorComboBox *comboBox; @property (weak, nonatomic) PTEditorTextField *textTextField; @property (weak, nonatomic) PTEditorTextField *response1TextField; @property (weak, nonatomic) PTEditorDialogueList *responseDialogue1List; @property (weak, nonatomic) PTEditorTextField *response2TextField; @property (weak, nonatomic) PTEditorDialogueList *responseDialogue2List; @property (weak, nonatomic) id <PTEditorListInputDialogueNodeDelegate> delegate; + (id)inputDialogueIndex:(NSInteger)index picOptions:(NSArray *)picOptions; @end
#import "PTEditorDialogueList.h" #import "cocos2d-ui.h" @interface PTEditorList () - (void)refreshButton; - (void)attachButton; @end @implementation PTEditorDialogueList + (id)listWithTitle:(NSString *)title picOptions:(NSArray *)picOptions { PTEditorDialogueList *list = [self listWithTitle:title]; list.picOptions = picOptions; return list; } #pragma mark - Popup Node - (void)showPopupNode { if (_popupNode == nil) { PTEditorDialogueListPopupNode *popupNode = [PTEditorDialogueListPopupNode popupNodeWithTitle:self.title items:self.items picOptions:_picOptions]; popupNode.delegate = self; [[CCDirector sharedDirector].runningScene addChild:popupNode]; _popupNode = popupNode; } } #pragma mark - Button Presses - (void)previewButtonPressed { [_listDialogueDelegate listDialoguePreview:self]; } #pragma mark - Content Size - (void)setContentSize:(CGSize)contentSize { [super setContentSize:contentSize]; _previewButton.position = CGPointMake(contentSize.width - 5.0f, _previewButton.position.y); [self fixButton]; [self refreshButton]; } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachPreviewButton]; } #pragma mark - Button layout - (void)attachButton { [super attachButton]; [self fixButton]; } - (void)fixButton { CGFloat width = self.contentSize.width - 50.0f; CCButton *button = self.button; button.maxSize = CGSizeMake(width, button.contentSize.height); button.position = CGPointMake(width / 2.0f, button.position.y); } #pragma mark - Preview Button layout - (void)attachPreviewButton { CGSize size = CGSizeMake(self.contentSize.width, 25.0f); CCButton *button = [CCButton buttonWithTitle:@"Preview" fontName:EF_DEFAULT_FONT_NAME fontSize:12.0f]; [button setTarget:self selector:@selector(previewButtonPressed)]; [button setLabelColor:[CCColor blackColor] forState:CCControlStateNormal]; button.maxSize = CGSizeMake(40.0f, size.height); button.preferredSize = button.maxSize; button.position = CGPointMake(size.width - 5.0f, size.height / 2.0f); button.anchorPoint = CGPointMake(1.0f, 0.5f); [self addChild:button]; _previewButton = button; } @end #pragma mark - PTEditorDialogueListPopupNode @implementation PTEditorDialogueListPopupNode + (id)popupNodeWithTitle:(NSString *)title items:(NSArray *)items picOptions:(NSArray *)picOptions { return [[self alloc] initWithTitle:title items:items picOptions:picOptions]; } - (id)initWithTitle:(NSString *)title items:(NSArray *)items picOptions:(NSArray *)picOptions { _picOptions = picOptions; self = [self initWithTitle:title items:items]; if (self) { } return self; } #pragma mark - Input Nodes - (id <PTEditorListInputNode>)generateInputNode:(NSInteger)index { return [self generateInputDialogueNode:index]; } - (CGFloat)inputNodeHeight { return [self inputDialogueNodeHeight]; } #pragma mark - Input Dialogue Nodes - (PTEditorListInputDialogueNode *)generateInputDialogueNode:(NSInteger)index { PTEditorListInputDialogueNode *inputDialogueNode = [PTEditorListInputDialogueNode inputDialogueIndex:index picOptions:_picOptions]; inputDialogueNode.delegate = self; inputDialogueNode.position = CGPointMake(20.0f, -[self inputNodeHeight] * (index + 1)); [self.containerNode addChild:inputDialogueNode]; [self.inputNodes addObject:inputDialogueNode]; return inputDialogueNode; } - (CGFloat)inputDialogueNodeHeight { return 190.0f; } #pragma mark - PTEditorListInputDialogueNodeDelegate - (void)listInputDialogueNodeWasEdited:(PTEditorListInputDialogueNode *)sender { [self inputNodeWasEdited:sender]; } @end #pragma mark - PTEditorListInputDialogueNode @implementation PTEditorListInputDialogueNode { NSInteger _index; NSArray *_picOptions; } + (id)inputDialogueIndex:(NSInteger)index picOptions:(NSArray *)picOptions { return [[self alloc] initWithIndex:index picOptions:picOptions]; } - (id)initWithIndex:(NSInteger)index picOptions:(NSArray *)picOptions { _index = index; _picOptions = picOptions; self = [self init]; if (self) { } return self; } - (void)setItem:(id)item { NSDictionary *dictionary = (NSDictionary *)item; _comboBox.value = [_picOptions indexOfObject:[dictionary objectForKey:@"pic"]]; _textTextField.stringValue = [dictionary objectForKey:@"text"]; NSArray *responses = [dictionary objectForKey:@"responses"]; NSInteger count = responses.count; if (count > 0) { NSDictionary *response = [responses objectAtIndex:0]; _response1TextField.stringValue = [response objectForKey:@"text"]; _responseDialogue1List.items = [response objectForKey:@"dialogue"]; } else { _response1TextField.stringValue = nil; _responseDialogue1List.items = nil; } if (count > 1) { NSDictionary *response = [responses objectAtIndex:1]; _response2TextField.stringValue = [response objectForKey:@"text"]; _responseDialogue2List.items = [response objectForKey:@"dialogue"]; } else { _response2TextField.stringValue = nil; _responseDialogue2List.items = nil; } } - (id)item { NSArray *responses = [NSArray arrayWithObjects: [NSDictionary dictionaryWithObjectsAndKeys: _response1TextField.stringValue, @"text", _responseDialogue1List.items, @"dialogue", nil], [NSDictionary dictionaryWithObjectsAndKeys: _response2TextField.stringValue, @"text", _responseDialogue2List.items, @"dialogue", nil], nil]; return [NSDictionary dictionaryWithObjectsAndKeys:[_picOptions objectAtIndex:_comboBox.value], @"pic", _textTextField.stringValue, @"text", responses, @"responses", nil]; } - (BOOL)isEmpty { return _comboBox.value == 0 && _textTextField.stringValue.length == 0 && _response1TextField.stringValue.length == 0 && _response2TextField.stringValue.length == 0; } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = CGSizeMake(200.0f, 180.0f); } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachComboBox]; [self attachTextTextField]; [self attachResponseTextFields]; [self attachResponseDialogueLists]; } #pragma mark - Combo Box layout - (void)attachComboBox { PTEditorComboBox *comboBox = [PTEditorComboBox comboBoxWithTitle:[NSString stringWithFormat:@"%d pic", _index + 1] options:_picOptions]; comboBox.delegate = self; comboBox.position = CGPointMake(0.0f, 135.0f); [self addChild:comboBox]; _comboBox = comboBox; } #pragma mark - Text Text Field layout - (void)attachTextTextField { PTEditorTextField *textField = [PTEditorTextField textFieldWithTitle:@"text"]; textField.delegate = self; textField.position = CGPointMake(0.0f, 90.0f); textField.contentSize = CGSizeMake(self.contentSize.width, textField.contentSize.height); [self addChild:textField]; _textTextField = textField; } #pragma mark - Response Text Fields layout - (void)attachResponseTextFields { CGFloat width = self.contentSize.width / 2.0f - 5.0f; PTEditorTextField *textField = [PTEditorTextField textFieldWithTitle:@"response 1"]; textField.delegate = self; textField.position = CGPointMake(0.0f, 45.0f); textField.contentSize = CGSizeMake(width, textField.contentSize.height); [self addChild:textField]; _response1TextField = textField; textField = [PTEditorTextField textFieldWithTitle:@"response 2"]; textField.delegate = self; textField.position = CGPointMake(self.contentSize.width / 2.0f + 10.0f, 45.0f); textField.contentSize = CGSizeMake(width, textField.contentSize.height); [self addChild:textField]; _response2TextField = textField; } #pragma mark - Response Dialogue Lists layout - (void)attachResponseDialogueLists { CGFloat width = self.contentSize.width / 2.0f - 5.0f; PTEditorDialogueList *dialogueList = [PTEditorDialogueList listWithTitle:@"branch 1" picOptions:_picOptions]; dialogueList.contentSize = CGSizeMake(width, dialogueList.contentSize.height); [self addChild:dialogueList]; _responseDialogue1List = dialogueList; dialogueList = [PTEditorDialogueList listWithTitle:@"branch 2" picOptions:_picOptions]; dialogueList.position = CGPointMake(self.contentSize.width / 2.0f + 10.0f, 0.0f); dialogueList.contentSize = CGSizeMake(width, dialogueList.contentSize.height); [self addChild:dialogueList]; _responseDialogue2List = dialogueList; } #pragma mark - PTEditorComboBoxDelegate - (void)comboBoxWasEdited:(PTEditorComboBox *)sender { [_delegate listInputDialogueNodeWasEdited:self]; } #pragma mark - PTEditorTextFieldDelegate - (void)textFieldWasEdited:(PTEditorTextField *)sender { [_delegate listInputDialogueNodeWasEdited:self]; } #pragma mark - PTEditorListDelegate - (void)listWasEdited:(PTEditorList *)sender { [_delegate listInputDialogueNodeWasEdited:self]; } @end
Alexander Wong http://alexanderwong.me

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Still slowly filling out our collection of characters! You can find this frazzled mom hanging out in Reno, taking a break from being a pack mule at the poker tables while her kids collect more and more plushie prizes at the midway.
Anna Koan - ankosquared.tumblr.com
We're making some good progress on Poker Puzzle Tour here at Ender's Fund. For one thing, our test builds don't have plain black splash screens anymore :P
Who's that smarmy-looking fellow in the background there? You'll just have to play to find out!
Anna Koan - ankosquared.tumblr.com
A couple cute grannies you might encounter on your poker puzzle journey! Do they remind you of your grandma?
Anna Koan - ankosquared.tumblr.com
A rough sketch of the latest floor plan map. Can anybody guess which casino this one is modeled after?
Cocos2d Custom TextField and ComboBox
I was away for a few days in Korea on a business trip so I'm playing catchup on Tumblr. I got back to the office midday Wednesday and thought it was about time to revamp the way we're designing and storing our levels for our new game, Poker Puzzle Tour.
I've started on building a level editor that serializes and deserializes data from a sqlite database. This gives us a much cleaner and more scalable way of managing our levels, however, it introduces some restrictions since we have to define and maintain a schema. I'm hoping, though, that we're far enough along that future changes will be nominal.
The sqlite side of the editor is pretty simple and there's not much that's new or nifty there to share, but I thought I'd share some quick classes I've written to handle the editor's UI. The code included is not meant for production release exactly. I've written it as a quick class I can reuse for building non-client facing UI. I'm sure though, that you could massage it into something more relatively easily.
Cocos2d's UI set is pretty sparse and only includes things like buttons, labels, and a very crude text field class. This is at no fault to the authors of the engine; I'm sure they have more important things to work on and more complex UI elements can be built relatively simply. But now I'm rambling...
Anyways, to help with building the editor UI, I found I needed a good combo box class, something that would let the user choose from multiple values, and I also needed a slightly more polished text field. I also wanted a simple way to label the UI elements, so each class is structured with a label on top followed by the actual UI input below.
The combo box is composed of a label and button. When the user taps the button, a full-screen popup is displayed that shows different options. Once an option is selected, the popup is automatically closed. The class takes an array of string labels and the index of the item selected can be retrieved as the value of the combo box.
#import "EFCCBaseNode.h" @class PTEditorComboBox; @class CCButton; @protocol PTEditorComboBoxDelegate - (void)comboBoxWasEdited:(PTEditorComboBox *)sender; @end @interface PTEditorComboBox : EFCCBaseNode @property (weak, nonatomic) CCLabelTTF *label; @property (weak, nonatomic) CCButton *button; @property (weak, nonatomic) CCNodeColor *buttonBackgroundNode; @property (weak, nonatomic) id delegate; @property (strong, nonatomic) NSString *title; @property (strong, nonatomic) NSArray *options; @property (nonatomic) NSInteger value; @property (nonatomic) BOOL enabled; + (id)comboBoxWithTitle:(NSString *)title options:(NSArray *)options; @end
#import "PTEditorComboBox.h" #import "cocos2d-ui.h" @implementation PTEditorComboBox { CCNode *_optionsNode; NSArray *_optionButtons; NSArray *_optionBackgroundNodes; } + (id)comboBoxWithTitle:(NSString *)title options:(NSArray *)options { PTEditorComboBox *comboBox = [PTEditorComboBox node]; comboBox.title = title; comboBox.options = options; return comboBox; } - (void)setEnabled:(BOOL)enabled { if (_enabled != enabled) { _enabled = enabled; _button.enabled = _enabled; _buttonBackgroundNode.color = _enabled ? [CCColor lightGrayColor] : [CCColor grayColor]; } } #pragma mark - Title - (void)setTitle:(NSString *)title { if (_title != title) { _title = title; _label.string = _title; } } #pragma mark - Value - (void)setValue:(NSInteger)value { if (_value != value) { _value = value; if (_value < _options.count) { [_button setTitle:[_options objectAtIndex:_value]]; } } } #pragma mark - Button Presses - (void)buttonPressed { if (_optionsNode == nil) { CCScene *scene = [CCDirector sharedDirector].runningScene; CGSize parentSize = scene.contentSize; EFCCBaseNode *node = [EFCCBaseNode node]; node.userInteractionEnabled = YES; node.terminateTouches = YES; node.contentSize = parentSize; node.zOrder = 999; [scene addChild:node]; _optionsNode = node; CCNodeColor *screenNode = [CCNodeColor nodeWithColor:[CCColor colorWithWhite:0.0f alpha:0.6f] width:parentSize.width height:parentSize.height]; [_optionsNode addChild:screenNode]; CGSize size = CGSizeMake(240.0f, 320.0f); CCNodeColor *containerNode = [CCNodeColor nodeWithColor:[CCColor whiteColor] width:size.width height:size.height]; containerNode.positionType = CCPositionTypeNormalized; containerNode.position = CGPointMake(0.5f, 0.5f); containerNode.anchorPoint = CGPointMake(0.5f, 0.5f); [_optionsNode addChild:containerNode]; CGSize toolbarSize = CGSizeMake(size.width, 30.0f); CCNodeColor *toolbarNode = [CCNodeColor nodeWithColor:[CCColor redColor] width:toolbarSize.width height:toolbarSize.height]; toolbarNode.position = CGPointMake(0.0f, size.height - toolbarSize.height); [containerNode addChild:toolbarNode]; CCLabelTTF *label = [CCLabelTTF labelWithString:_title fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f dimensions:toolbarSize]; label.horizontalAlignment = CCTextAlignmentCenter; label.verticalAlignment = CCVerticalTextAlignmentCenter; label.anchorPoint = CGPointZero; [toolbarNode addChild:label]; NSMutableArray *buttons = [NSMutableArray array]; NSMutableArray *buttonBackgroundNodes = [NSMutableArray array]; CGSize buttonSize = CGSizeMake(180.0f, 25.0f); CGFloat margin = 10.0f; CGFloat x = (size.width - buttonSize.width) / 2.0f; CGFloat y = size.height - toolbarSize.height - buttonSize.height - 20.0f; NSInteger value = 0; for (NSString *option in _options) { CCNodeColor *buttonBackgroundNode = [CCNodeColor nodeWithColor:[CCColor lightGrayColor] width:buttonSize.width height:buttonSize.height]; buttonBackgroundNode.position = CGPointMake(x, y); [containerNode addChild:buttonBackgroundNode]; [buttonBackgroundNodes addObject:buttonBackgroundNode]; CCButton *button = [CCButton buttonWithTitle:option fontName:EF_DEFAULT_FONT_NAME fontSize:12.0f]; __weak PTEditorComboBox *weakSelf = self; [button setBlock:^(id sender) { // update value weakSelf.value = value; // close [_optionsNode removeFromParentAndCleanup:YES]; _optionsNode = nil; _optionButtons = nil; _optionBackgroundNodes = nil; [_delegate comboBoxWasEdited:weakSelf]; }]; [button setLabelColor:[CCColor blackColor] forState:CCControlStateNormal]; button.preferredSize = CGSizeMake(0.0f, buttonSize.height); button.maxSize = buttonSize; button.position = CGPointMake(x + buttonSize.width / 2.0f, y + buttonSize.height / 2.0f); button.anchorPoint = CGPointMake(0.5f, 0.5f); [containerNode addChild:button]; [buttons addObject:button]; // iterate value++; y -= buttonSize.height + margin; } _optionButtons = buttons; _optionBackgroundNodes = buttonBackgroundNodes; } } #pragma mark - Update - (void)update:(CCTime)delta { NSInteger value = 0; for (CCButton *button in _optionButtons) { CCNodeColor *backgroundNode = [_optionBackgroundNodes objectAtIndex:value]; backgroundNode.color = _value == value || button.highlighted ? [CCColor redColor] : [CCColor lightGrayColor]; // iterate value++; } } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = CGSizeMake(130.0f, 45.0f); } - (void)setContentSize:(CGSize)contentSize { [super setContentSize:contentSize]; _label.contentSize = CGSizeMake(contentSize.width, _label.contentSize.height); _buttonBackgroundNode.contentSize = CGSizeMake(contentSize.width, _buttonBackgroundNode.contentSize.height); _button.preferredSize = CGSizeMake(contentSize.width, _button.contentSize.height); } #pragma mark - Data - (void)initializeData { [super initializeData]; _value = -1; _enabled = YES; } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachLabel]; [self attachButton]; } #pragma mark - Label layout - (void)attachLabel { CCLabelTTF *label = [CCLabelTTF labelWithString:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:12.0f dimensions:CGSizeMake(self.contentSize.width, 20.0f)]; label.color = [CCColor blackColor]; label.verticalAlignment = CCVerticalTextAlignmentCenter; label.adjustsFontSizeToFit = YES; label.position = CGPointMake(0.0f, 25.0f); label.anchorPoint = CGPointZero; [self addChild:label]; _label = label; } #pragma mark - Button layout - (void)attachButton { CCNodeColor *node = [CCNodeColor nodeWithColor:[CCColor lightGrayColor] width:self.contentSize.width height:25.0f]; [self addChild:node]; _buttonBackgroundNode = node; CCButton *button = [CCButton buttonWithTitle:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f]; [button setTarget:self selector:@selector(buttonPressed)]; [button setLabelColor:[CCColor blackColor] forState:CCControlStateNormal]; button.preferredSize = CGSizeMake(0.0f, 25.0f); button.maxSize = CGSizeMake(self.contentSize.width, 25.0f); button.position = CGPointMake(self.contentSize.width / 2.0f, 12.5f); button.anchorPoint = CGPointMake(0.5f, 0.5f); [self addChild:button]; _button = button; } @end
The text field is also composed of a label, a button, and a CCTextField. It's a little over engineered but I found I had to build it this way to make the original CCTextField implementation play nicely; the original CCTextField class is very touch hungry and doesn't respect z-ordering at all. The CCTextField class basically works kind of like a browser styled input field hack - it constantly updates the position of a UITextField. To circumvent this, I basically hide the CCTextField until the user clicks on the button to edit. The button then gets hidden, and the CCTextField is shown and given focus. When the user is done editing, I hide the CCTextField and show the button.
The text field takes a string, integer, float, or double values. What's important is to set and read from the same property.
#import "EFCCBaseNode.h" @class PTEditorTextField; @class CCButton; @class CCTextField; @protocol PTEditorTextFieldDelegate - (void)textFieldWasEdited:(PTEditorTextField *)sender; @end @interface PTEditorTextField : EFCCBaseNode @property (weak, nonatomic) CCLabelTTF *label; @property (weak, nonatomic) CCButton *button; @property (weak, nonatomic) CCTextField *textField; @property (weak, nonatomic) CCNodeColor *textFieldBackgroundNode; @property (weak, nonatomic) id delegate; @property (strong, nonatomic) NSString *title; @property (strong, nonatomic) NSString *stringValue; @property (nonatomic) NSInteger integerValue; @property (nonatomic) CGFloat floatValue; @property (nonatomic) double doubleValue; @property (nonatomic) BOOL enabled; + (id)textFieldWithTitle:(NSString *)title; @end
#import "PTEditorTextField.h" #import "cocos2d-ui.h" @implementation PTEditorTextField + (id)textFieldWithTitle:(NSString *)title { PTEditorTextField *textField = [PTEditorTextField node]; textField.title = title; return textField; } - (void)setEnabled:(BOOL)enabled { if (_enabled != enabled) { _enabled = enabled; _textField.enabled = _enabled; _textFieldBackgroundNode.color = _enabled ? [CCColor lightGrayColor] : [CCColor grayColor]; } } #pragma mark - Title - (void)setTitle:(NSString *)title { if (_title != title) { _title = title; _label.string = _title; } } #pragma mark - Values - (void)setStringValue:(NSString *)stringValue { _textField.string = stringValue; _button.title = _textField.string ? _textField.string : @""; } - (NSString *)stringValue { return _textField.string; } - (void)setIntegerValue:(NSInteger)integerValue { _textField.string = [NSString stringWithFormat:@"%d", integerValue]; _button.title = _textField.string ? _textField.string : @""; } - (NSInteger)integerValue { return [_textField.string integerValue]; } - (void)setFloatValue:(CGFloat)floatValue { _textField.string = [NSString stringWithFormat:@"%.02f", floatValue]; _button.title = _textField.string ? _textField.string : @""; } - (CGFloat)floatValue { return [_textField.string floatValue]; } - (void)setDoubleValue:(double)doubleValue { [self setFloatValue:doubleValue]; } - (double)doubleValue { return [self floatValue]; } #pragma mark - Update - (void)update:(CCTime)delta { if (_visible && !_button.visible && !_textField.textField.isFirstResponder) { _button.visible = YES; _textField.visible = NO; _button.title = _textField.string ? _textField.string : @""; } } #pragma mark - Button Presses - (void)buttonPressed { if (_button.visible) { _button.visible = NO; _textField.visible = YES; [_textField.textField becomeFirstResponder]; } } #pragma mark - Content Size - (void)initializeContentSize { self.contentSize = CGSizeMake(130.0f, 45.0f); } - (void)setContentSize:(CGSize)contentSize { [super setContentSize:contentSize]; _label.contentSize = CGSizeMake(contentSize.width, _label.contentSize.height); _textFieldBackgroundNode.contentSize = CGSizeMake(contentSize.width, _textFieldBackgroundNode.contentSize.height); _button.preferredSize = CGSizeMake(contentSize.width, _button.contentSize.height); _textField.preferredSize = CGSizeMake(contentSize.width, _textField.contentSize.height); } #pragma mark - Data - (void)initializeData { [super initializeData]; _enabled = YES; } #pragma mark - Layout - (void)initializeLayout { [super initializeLayout]; [self attachLabel]; [self attachTextField]; } #pragma mark - Label layout - (void)attachLabel { CCLabelTTF *label = [CCLabelTTF labelWithString:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:12.0f dimensions:CGSizeMake(self.contentSize.width, 20.0f)]; label.color = [CCColor blackColor]; label.verticalAlignment = CCVerticalTextAlignmentCenter; label.adjustsFontSizeToFit = YES; label.position = CGPointMake(0.0f, 25.0f); label.anchorPoint = CGPointZero; [self addChild:label]; _label = label; } #pragma mark - TextField layout - (void)attachTextField { CCNodeColor *node = [CCNodeColor nodeWithColor:[CCColor lightGrayColor] width:self.contentSize.width height:25.0f]; [self addChild:node]; _textFieldBackgroundNode = node; CGSize size = CGSizeMake(self.contentSize.width, 25.0f); CCButton *button = [CCButton buttonWithTitle:@"" fontName:EF_DEFAULT_FONT_NAME fontSize:14.0f]; [button setTarget:self selector:@selector(buttonPressed)]; [button setLabelColor:[CCColor blackColor] forState:CCControlStateNormal]; button.preferredSize = size; button.anchorPoint = CGPointZero; [self addChild:button]; _button = button; CCTextField *textField = [[CCTextField alloc] init]; textField.preferredSize = size; textField.fontSize = 14.0f; textField.anchorPoint = CGPointZero; [self addChild:textField]; _textField = textField; _textField.visible = NO; } @end
One quick thing to note, you'll find that many of my custom classes subclass EFCCBaseNode or EFCCBaseScene. These are just wrapper classes around CCNode and CCScene respectively where I've put in some callbacks that helps me organize my coding better. I'll create a separate post explaining this on my personal blog.
Alexander Wong http://alexanderwong.me

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
Some updated icons for the main screen with a comparison to the older buttons. I also decided to give the top and bottom bars a more art deco look, they were just boring rectangles before. A little classy flair to accommodate your experience in poker, puzzles and fun. :)
Jessica Jurado www.shekarr.com
Meet Lucky Larry, another character from our motley crew. Players will meet this guy in Atlantic City.
Anna Koan ankosquared.tumblr.com
Planning out the animations for the board, I promise you super fun and radical coolness at the end. Up top are early assets for some of the animations I'll be doing myself, others will be planned out in another program.
Gameboard design is not final yet either but if you look at the bottom image, that is an early prototype of individualized game boards for every hotel. This one's for the Rock Star Hotel. What would the other's look like? :)
Jessica Jurado www.shekarr.com
Let's Get Bombed: The game will feature special exploding puzzle pieces or "bombs" that appear when you find certain poker hands. These are just a few of the variations we tried. Ultimately, we settled on the round Poker Chips mainly for consistency with the theme and overall readability.
An early, business type, teaser for our upcoming title: Poker Puzzle Tour!
Alexander Wong http://alexanderwong.me

Anya is live and ready to show you everything. Watch her strip, dance, and perform exclusive shows just for you. Interact in real-time and make your fantasies come true.
Free to watch • No registration required • HD streaming
There are a variety of characters you meet and play against throughout Poker Puzzle Tour. This guy likes to call himself "The Eddie".
Anna Koan ankosquared.tumblr.com annakoan.com
CCParticleSystem Prewarm Extension / Category
We've been playing with particle effects in our latest title, Poker Puzzle Tour. It's the first time we've used particle systems and it's hard to not get too carried away with them. The joke in the office is to not go all lens flare crazy with it - not overuse them too much.
Here's a small extension for Cocos2D's CCParticleSystem I put together last week to aid our efforts. The Unity game engine lets you "prewarm" your particle effects, basically start them mid-cycle. Cocos2D doesn't currently have the ability to do this, so I hacked together a simple "prewarm" method. Nothing fancy, but it's been working well for us.
@implementation CCParticleSystem (EF) - (void)prewarm { CCTime elapsed = 0.0; CCTime prewarm = _life + _lifeVar / 2.0; while (elapsed < prewarm) { CCTime dt = [EFMathHelper randomDoubleBetweenMin:0.0 max:0.1]; if (dt > 0.0) { elapsed += dt; [self update:dt]; } } } @end
Particle Effect at Initialization w/ Prewarm
Alexander Wong http://alexanderwong.me