Hit Detection on Scaled or Rotated Lines?

Hi,
I'm writing a java program in which I paint a number of line segments.
I've added the ability to scale or rotate the scene. Now, if the scene
is neither scaled or rotated, then detecting when the mouse pointer
is over a particular line is not especially difficult. I just iterate through
all the line objects and compare their coordinates with the mouse's
coordinates.
But I can't figure how to detect when the mouse is over a line when the
scene has been scaled and/or rotated. I guess this problem requires
a bit of maths - something I'm bit rusty at. Can someone help me?
Thanks.

import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.Hashtable;
import javax.swing.*;
import javax.swing.event.*;
public class TransformSelection extends JPanel implements ChangeListener {
    JSlider rotateSlider;
    JSlider scaleSlider;
    Polygon polygon;
    Line2D[] lines;
    int selectedIndex = -1;
    Color[] colors = {
        Color.red, Color.green.darker(), Color.blue, Color.magenta, Color.orange
    AffineTransform at = new AffineTransform();
    double theta = 0;
    double scale = 1.0;
    public void stateChanged(ChangeEvent e) {
        JSlider slider = (JSlider)e.getSource();
        int value = slider.getValue();
        double cx = getWidth()/2.0;
        double cy = getHeight()/2.0;
        if(slider == rotateSlider) {
            theta = Math.toRadians(value);
        if(slider == scaleSlider) {
            scale = value/100.0;
        at.setToTranslation((1.0-scale)*cx, (1.0-scale)*cy);
        at.scale(scale, scale);
        at.rotate(theta, cx, cy);
        repaint();
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2 = (Graphics2D)g;
        g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                            RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL,
                            RenderingHints.VALUE_STROKE_PURE);
        if(lines == null) {
            initLines();
        AffineTransform orig = g2.getTransform();
        g2.setTransform(at);
        //g2.setPaint(Color.blue);
        //g2.draw(polygon);
        g2.setPaint(Color.red);
        for(int j = 0; j < lines.length; j++) {
            g2.setPaint(colors[j]);
            g2.draw(lines[j]);
            if(j == selectedIndex) {
                g2.setPaint(Color.red);
                double cx = (lines[j].getX1() + lines[j].getX2())/2;
                double cy = (lines[j].getY1() + lines[j].getY2())/2;
                g2.draw(new Ellipse2D.Double(cx-4, cy-4, 8, 8));
        g2.setTransform(orig);
    public void setSelectedIndex(int index) {
        selectedIndex = index;
        repaint();
    private void initLines() {
        int w = getWidth();
        int h = getHeight();
        double cx = w/2.0;
        double cy = h/2.0;
        int R = Math.min(w,h)/6;
        int sides = 5;
        int[][]xy = generateShapeArrays(w/2, h/2, R, sides);
        polygon = new Polygon(xy[0], xy[1], 5);
        lines = new Line2D[sides];
        double theta = -Math.PI/2;
        for(int j = 0; j < sides; j++) {
            double x1 = cx + (R/2)*Math.cos(theta);
            double y1 = cy + (R/2)*Math.sin(theta);
            double x2 = polygon.xpoints[j];
            double y2 = polygon.ypoints[j];
            lines[j] = new Line2D.Double(x1, y1, x2, y2);
            theta += 2*Math.PI/sides;
    private JPanel getControls() {
        rotateSlider = new JSlider(JSlider.HORIZONTAL, -180, 180, 0);
        rotateSlider.setMajorTickSpacing(30);
        rotateSlider.setMinorTickSpacing(10);
        rotateSlider.setPaintTicks(true);
        rotateSlider.setPaintLabels(true);
        rotateSlider.addChangeListener(this);
        scaleSlider = new JSlider(JSlider.HORIZONTAL, 50, 200, 100);
        scaleSlider.setMajorTickSpacing(50);
        scaleSlider.setMinorTickSpacing(10);
        scaleSlider.setPaintTicks(true);
        scaleSlider.setLabelTable(getLabelTable(50, 200, 50));
        scaleSlider.setPaintLabels(true);
        scaleSlider.addChangeListener(this);
        JPanel panel = new JPanel(new GridBagLayout());
        GridBagConstraints gbc = new GridBagConstraints();
        gbc.weightx = 1.0;
        gbc.fill = gbc.HORIZONTAL;
        gbc.gridwidth = gbc.REMAINDER;
        panel.add(rotateSlider, gbc);
        panel.add(scaleSlider, gbc);
        return panel;
    private Hashtable getLabelTable(int min, int max, int inc) {
        Hashtable<Integer,JComponent> table = new Hashtable<Integer,JComponent>();
        for(int j = min; j <= max; j += inc) {
            String s = String.format("%d%%", j);
            table.put(new Integer(j), new JLabel(s));
        return table;
    private int[][] generateShapeArrays(int cx, int cy, int R, int sides) {
        int radInc = 0;
        if(sides % 2 == 0) {
            radInc = 1;
        int[] x = new int[sides];
        int[] y = new int[sides];
        for(int i = 0; i < sides; i++) {
            x[i] = cx + (int)(R * Math.sin(radInc*Math.PI/sides));
            y[i] = cy - (int)(R * Math.cos(radInc*Math.PI/sides));
            radInc += 2;
        // keep base of triangle level
        if(sides == 3) {
            y[2] = y[1];
        return new int[][] { x, y };
    public static void main(String[] args) {
        TransformSelection test = new TransformSelection();
        test.addMouseListener(new LineSelector(test));
        JFrame f = new JFrame("click on lines");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.getContentPane().add(test);
        f.getContentPane().add(test.getControls(), "Last");
        f.setSize(400,400);
        f.setLocation(200,200);
        f.setVisible(true);
class LineSelector extends MouseAdapter {
    TransformSelection transformSelection;
    Rectangle net;
    int lastSelectedIndex;
    final int SIDE = 4;
    public LineSelector(TransformSelection ts) {
        transformSelection = ts;
        net = new Rectangle(SIDE, SIDE);
    public void mousePressed(MouseEvent e) {
        net.setLocation(e.getX() - SIDE/2, e.getY() - SIDE/2);
        AffineTransform at = transformSelection.at;
        Line2D[] lines = transformSelection.lines;
        for(int j = 0; j < lines.length; j++) {
            Shape xs = at.createTransformedShape(lines[j]);
            if(xs.intersects(net)) {
                transformSelection.setSelectedIndex(j);
                lastSelectedIndex = j;
                break;
}

Similar Messages

  • Hit detection between a line and a UIView?

    Hi all,
    I'm trying to figure out if a UIView I've got on the screen is intersecting a line I'm drawing.
    Here's the code for drawRect:
    -(void)drawRect:(CGRect)rect
    // Get the current graphics context and clear it
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextClipToRect(ctx, CGRectMake(0, 0, 240, 320));
    CGContextClearRect(ctx, rect);
    // The line style
    CGContextSetLineWidth(ctx, 3.0);
    CGContextSetLineCap(ctx, kCGLineCapRound);
    CGContextSetRGBStrokeColor(ctx, 1.0, 1.0, 1.0, 1.0);
    // Create the line
    CGContextMoveToPoint(ctx, source.x, source.y);
    CGContextAddLineToPoint(ctx, dest.x, dest.y);
    // Draw the line
    CGContextDrawPath(ctx, kCGPathStroke);
    CGContextStrokePath(ctx);
    That draws a line from and to wherever I need it, but when I draw it over a UIView that's already on the screen, I need to know if the centre point of the UIView is on that line. So, if you have a line going from 0,0 to 10,10, you have points at 1,1 2,2 3,3 ... 10,10. If the centre point of the UIView is at, say, 3,3, it would be on that line.
    I've seen use of the CGContextPathContainsPoint method, but I can't get it working - my line doesn't draw. Here's the code for drawRect:
    -(void)drawRect:(CGRect)rect
    // Get the current graphics context and clear it
    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextClipToRect(ctx, CGRectMake(0, 0, 240, 320));
    CGContextClearRect(ctx, rect);
    // The line style
    CGContextSetLineWidth(ctx, 3.0);
    CGContextSetLineCap(ctx, kCGLineCapRound);
    CGContextSetRGBStrokeColor(ctx, 1.0, 1.0, 1.0, 1.0);
    // Create the path
    CGMutablePathRef linePath = CGPathCreateMutable();
    // Move to the source point and add a line to the destination point
    CGPathMoveToPoint(linePath, NULL, source.x, source.y);
    CGPathAddLineToPoint(linePath, NULL, dest.x, dest.y);
    // Draw the line
    CGPathDrawingMode(kCGPathStroke);
    CGContextDrawPath(ctx, kCGPathStroke);
    CGContextStrokePath(ctx);
    // Save the graphics state before doing the hit detection
    CGContextSaveGState(ctx);
    CGPathRef path = linePath;
    CGContextAddPath(ctx, path);
    if(CGContextPathContainsPoint(ctx, baddie, kCGPathStroke)) {
    NSLog(@"Yes");
    CGContextRestoreGState(ctx);
    I'm clearly doing something wrong here, but I can't quite figure it out.
    Any help much appreciated!

    I'm tearing my hair out with this. This is simple maths!!! Every point I put into the formula works fine, but when it's in code it fails. I think it's something to do with the frame I'm using...
    This is set in the init method:
    CGRect frame = CGRectMake(40.0, 60.0, 240.0, 320.0);
    The source and destination of the line I'm drawing, and the point I want to check (myPoint) are passed in and set up as follows (in their respective setter methods):
    source = CGPointMake(pos.x - 40.0, pos.y - 60.0);
    dest = CGPointMake(pos.x - 40.0, pos.y - 60.0);
    myPoint = CGPointMake(pos.x - 40.0, pos.y - 60.0);
    They have 40 and 60 pixels removed as the co-ords I'm passing in are the location on the iPhone screen (320x480). I have to subtract those values to get the top-left corner of the frame I'm drawing into, i.e. 40, 60 on the screen is actually 0, 0 of the frame.
    Now I draw the line in the drawRect method:
    CGMutablePathRef linePath = CGPathCreateMutable();
    CGPathMoveToPoint(linePath, NULL, source.x, source.y);
    CGPathAddLineToPoint(linePath, NULL, dest.x, dest.y);
    And here's where I check whether the point has touched the line:
    float m = (source.y - dest.y) / (source.x - dest.x);
    float y = (m * (source.x - myPoint.x)) + myPoint.y;
    if((y >= source.y - 3) && (y <= source.y + 3) && (myPoint.x >= source.x) && (myPoint.x <= dest.x)) // ±3 pixels for tolerance
    NSLog(@"Point hit the line!");
    What am I doing wrong?!
    The whole premise of my game rests on this one simple little problem. I've spent two weeks writing the rest of it, and a week writing THIS one part! Grrr.
    Any help much appreciated. If I can't get this done within a week, pop along to London and see a grown man cry.

  • Docsis 2.0 and 1.1 cable modems are not detected via UBR-MC20X20V-5D line card

    Hi All,
    We have uBR10K series CMTS and recently installed UBR-MC20X20V-5D line card, requirement is to configure this line card to support docsis 1.1 and 2.0. Problem is after finished the configurations modems (Hitron and Motorola) are not detected by the system. means no modem mac address listing under "Show cable modem" command. 
    Our CMTS has the following components
    ESR-PRE2: x1
    ESR-PRE-MEM-FD128: x1
    UBR10-DTCC:  x2
    UBR-MC20X20V-5D: x1
    iOS version:     12.2(33)SCE3
    Part of running-config as follows
    cable spectrum-group 13 band 22800000 26600000
    controller Integrated-Cable 8/0/0
     rf-channel 0 cable downstream channel-id 145
     rf-channel 0 frequency 501012500 annex B modulation 256qam interleave 32
     rf-channel 0 rf-power 59.0
     no rf-channel 0 rf-shutdown
    interface Cable8/0/0
     no cable packet-cache
     cable bundle 1
     cable upstream max-ports 4
     cable upstream 0 connector 0
     cable upstream 0 spectrum-group 13
     cable upstream 0 channel-width 3200000 3200000
     cable upstream 0 docsis-mode tdma
     cable upstream 0 minislot-size 2
     cable upstream 0 range-backoff 3 6
     cable upstream 0 modulation-profile 21
     no cable upstream 0 shutdown
    diag output attached herewith. Please any one advice on how to resolve this issue.
    Thanks in advance.

    Hi All,
    We have uBR10K series CMTS and recently installed UBR-MC20X20V-5D line card, requirement is to configure this line card to support docsis 1.1 and 2.0. Problem is after finished the configurations modems (Hitron and Motorola) are not detected by the system. means no modem mac address listing under "Show cable modem" command. 
    Our CMTS has the following components
    ESR-PRE2: x1
    ESR-PRE-MEM-FD128: x1
    UBR10-DTCC:  x2
    UBR-MC20X20V-5D: x1
    iOS version:     12.2(33)SCE3
    Part of running-config as follows
    cable spectrum-group 13 band 22800000 26600000
    controller Integrated-Cable 8/0/0
     rf-channel 0 cable downstream channel-id 145
     rf-channel 0 frequency 501012500 annex B modulation 256qam interleave 32
     rf-channel 0 rf-power 59.0
     no rf-channel 0 rf-shutdown
    interface Cable8/0/0
     no cable packet-cache
     cable bundle 1
     cable upstream max-ports 4
     cable upstream 0 connector 0
     cable upstream 0 spectrum-group 13
     cable upstream 0 channel-width 3200000 3200000
     cable upstream 0 docsis-mode tdma
     cable upstream 0 minislot-size 2
     cable upstream 0 range-backoff 3 6
     cable upstream 0 modulation-profile 21
     no cable upstream 0 shutdown
    diag output attached herewith. Please any one advice on how to resolve this issue.
    Thanks in advance.

  • Hit detection

    i have included my code below for bullets in my game. the
    bullets are added to the stage when the mouse is clicked anywhere.
    easy enough... now the question i have is at the bottom of my
    shooter function. i am trying to detect when a bullet (boxr) hits
    my target.
    it could have something to do with the bullets being
    generated inside that function and the target being just a movie
    clip on the stage with the instance name "target". im not sure. any
    help would be greatly appreciated.

    awesome! i didn't realize you had to detect for a hit each
    frame. i just thought it was triggered when the two movie clips
    were on top of each other. thanks!

  • Rotating line width

    A tangental question to the arrow issue previously posted. I tagged this question to the end of the other thread but it may have gotten lost.
    http://www.youtube.com/watch?v=RnRZn_p8MFk
    In the example I gave the arrow thickness was only in the vertical plane. I have been playing with this and can't seem to figure out how to get the width to be horizontal.
    I've tried making the line straight, add the width, then rotate the line in X, but then I can't get it to curve.
    I changed the Brush Type to Airbrush and by turning on Local 3D and I can make the Line "tubular" but I can't get the ribbon look I've trying to achieve.
    I just wish it was a simple as just being able to rotate the line thickness.

    If you're referring to the manner in which the line/arrow curves (on the edge vs on the flat side), then you've discovered a fundamental problem with the line due to the fact that it's a 2D element and not a 3D element.
    The only real way to get a line to bend along its spine is to use a 3D replicator using a thin rectangle as the source. Replicators can be 3D and can be positioned in such a way to mimic a 3D line. However, you'd have to attach arrows manually, and then animating it is a whole other can o'worms. Not to mention the fact that you'd have to create a lot of replicates for even a single line which will significantly drive down performance.
    Andy

  • How do i detect the maximum number of lines

    Situation:
    I have a textfield that displays about 8 lines of text before
    the content would need to be scrolled to view the remaining
    content.
    Question
    Rather than having some ActionScript that is constantly
    trying to scroll the field, how do i detect the following.
    How do i determine the maximum number of lines that may be
    displayed in a textField (or any type of text field) before
    scrolling would be needed?
    Please specify the method. Thank you.

    When tracing the output using the bottomScroll, it only tells
    me how many liines I have output to the textfiedl, it does not tell
    me how many lines the textfield can hold.
    How do I determine how many lines a textfield can
    hold?

  • Complex Hit Test and Scaling

    Hi
    I performed hitTestObject using the code found here
    http://www.tink.ws/blog/as-30-hittest/
    Everything worked fine.
    But by performing below operations, hitTest is not working :
    1. Created a movieclip in my main fla file
    2. Loaded hitTest swf in the above movieclip in my main fla file.
    3. Scaled the above movieclip to 0.8;
    This 3rd point is the problem.
    When I remove the scale, no problem occurs.
    Need help.
    Thanks,
    Rabin.

    Look up the HitTest-class and search for the getDrawMatrix() function.
    protected static function getDrawMatrix( target:DisplayObject, hitRectangle:Rectangle, accuracy:Number ):Matrix {
                var localToGlobal:Point;
                var matrix:Matrix;
                var rootConcatenatedMatrix:Matrix = target.root.transform.concatenatedMatrix;
                localToGlobal = target.localToGlobal( new Point() );
                matrix = target.transform.concatenatedMatrix;
                matrix.tx = localToGlobal.x  - hitRectangle.x;
                matrix.ty = localToGlobal.y  - hitRectangle.y;
                //Adjust the following lines, also be sure that all your hittesting/hittested sprites have the same registration point setting
                matrix.tx = matrix.tx - 150;
                matrix.ty = matrix.ty - 182;
                matrix.a = matrix.a / rootConcatenatedMatrix.a;
                matrix.d = matrix.d / rootConcatenatedMatrix.d;
                if ( accuracy != 1 ) {
                    matrix.scale( accuracy, accuracy );
                return matrix;

  • Detecting mouse click on a line

    I'm learning making GUI apps in Java.
    Here is my problem. Suppose I draw a line on a JPanel. If I want to find out if the line is clicked or not, what is the best way to do it?
    I did some research, looked at API. If I suppose my line is Line2D, then since its a line it doesn't have an area, so its contains method always returns false (..from API). So i dig around some more and came up with the solution of getting the shape from the stroke and calling its contains method.
    This is a code for what i mean..
    private Line2D.Double testLine;
    //mouse clicked event
    public void mouseClicked(MouseEvent e) {
            int x = e.getX();
            int y = e.getY();
            BasicStroke stroke = new BasicStroke(4);
            Shape testShape = stroke.createStrokedShape(testLine);
            if(testShape.contains(x,y)){
                System.out.println("this will be printed if clicked on line");
        }Well, the above solution works fine.
    Is it the right way of doing it or is there a better way around for this?
    Any help will be appreciated.
    Thanks.

    When trying to test if a line was pressed I usually test if the distance between the mouse coordinates and the line is smaller than some constant (usually 5 pixels).
    For this you have to write your own code to calculate the distance between a point and a line.

  • Scaling and rotating with motion tween

    This is a ridiculously easy problem but I'm drawing a mental blank at how to do it so in advance I apologize for the simplicity. I'm trying to get a movie clip to rotate and scale automatically without being clicked. I would like it to gradually rotate by 90 degrees and scale by 150%, but I can't figure out how to get a motion tween to do it and am having to do it manually frame by frame. What is the code to do this?
    Thank you!

    If you are using CS4 or newer, make sure you are using the classic tween for what you described you tried. The only wondering I have is you mentioning a clip twice... if you are inside the movieclip you cannot rotate and scale it from there.  So is there a clip inside the clip, and is it the inner clip that you are trying to tween?  The object you scale and rotate must be a library symbol.

  • Hit Detection on array

    Hi i have a snake game, that after time loads sprites in an array to make the snake grow. Just wondering how i would go about adding a hit so when the head of the snake hits the body something happens. Below is the full document class code. Any pointers to what type of code would be massively helpful.
    <code>
    package {
    import flash.display.Sprite;
    import flash.events.KeyboardEvent;
    import flash.events.TimerEvent;
    import flash.ui.Keyboard;
    import flash.utils.Timer;
    import flash.display.MovieClip;
    import flash.utils.getTimer;
    import flash.text.TextField;
    import flash.events.Event;
    [SWF(width='430', height='430', frameRate='30')]
    public class Snake extends MovieClip{
    private const SPEED :uint = 25;//lower = faster
    private const snakeAttach :uint = 400;//lower = faster
    private const count:         uint = 10;
    private const DIM :int = 50; //keep this number uneven to have the snake starting in the middle
    private const INITIAL_SIZE :int = 3; //keep this lower then DIM/2
    private var stopped :Boolean;
    private var left :Boolean;
    private var right :Boolean;
    private var up :Boolean;
    private var down :Boolean;
    private var size :Number;
    private var food :Sprite;
    private var tmr :Timer;
    private var count1          :Timer;
    private var addSnake :Timer;
    private var curI :Number;
    private var curJ :Number;
    private var snake :Array;
    private var grid :Array;
    private var sp               :Sprite;
    private var _start:uint;
    public var myTextBox:TextField = new TextField();
    public function Snake(){
    addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    private function onAddedToStage(event:Event):void {
    removeEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
    stage.addEventListener(KeyboardEvent.KEY_DOWN,changeDir);
    size = stage.stageWidth / DIM; //change grid size
    curI = curJ = Math.floor(DIM * 0.5); //change grid size
    initSnake();
    fillGrid();
    addTimer();
    addChild(myTextBox);
    count1 = new Timer(count);
    count1.addEventListener(TimerEvent.TIMER,stopWatch);
    count1.start();
    addSnake = new Timer(snakeAttach);
    addSnake.addEventListener(TimerEvent.TIMER,placeFood);
    addSnake.start();
    tmr = new Timer(SPEED);
    tmr.addEventListener(TimerEvent.TIMER,move);
    tmr.start();
    private function stopWatch(event:TimerEvent):void{
    myTextBox.text = (count1.currentCount / 100).toString();
    public function addTimer():void{ //timer
    var myTextBox:TextField = new TextField();
    addChild(myTextBox);
    private function fillGrid():void{  //grid
    grid = Make2DArray();
    for (var i:uint = 0; i < DIM; i++){
    for (var j:uint = 0; j < DIM; j++){
    var sp:Sprite = new Sprite();
    sp.graphics.beginFill(0xD7E0FC);
    sp.graphics.lineStyle(1,0xF5F5F5);
    sp.graphics.drawRect(0, 0, size  - 1, size - 1);
    sp.x = i * size;
    sp.y = j * size;
    addChild(sp);
    grid[i][j] = sp;
    private function Make2DArray():Array{   //for the grid
    var a:Array = new Array(DIM);
    for(var i:uint = 0; i < a.length; i++){
        a[i] = new Array(DIM);
    return a;
    private function initSnake():void{ //initialises the snake
    var center:Number = Math.floor(DIM * 0.5) * size;
    snake = new Array(INITIAL_SIZE);
    for (var i:uint = 0; i < INITIAL_SIZE; i++){
    var sp:Sprite = makeItem();      //adds a body part of makeItem
    sp.x = center;
    sp.y = center + i * size;
    addChild(sp); //adds to the stage
    snake[i] = sp;  //sets the index to one
    snake.reverse();
    private function makeItem(c:uint = 0):Sprite{  //graphics for item
    var s:Sprite = new Sprite();
    s.graphics.beginFill(c);
    s.graphics.lineStyle(2,0x3800E0);
    s.graphics.drawRect(0, 0, size, size);
    return s;
    private function placeFood(event:TimerEvent):void{  
    var rndI:uint = Math.floor(Math.random() * DIM);  //sets a random integer based on the the floor
    var rndJ:uint = Math.floor(Math.random() * DIM);
    var rndX:Number = grid[rndI][rndJ].x; // sets a grid position for the food item to go
    var rndY:Number = grid[rndI][rndJ].y;
    if (food != null) removeChild(food);  //if there is food on the grid removes the food from the board
    food = makeItem(Math.random() * 0xFFFFFF);// random color
    food.x = rndX;
    food.y = rndY;
    addChild(food); //adds the food to the board
    for (var i:uint = 0; i < snake.length; i++){
    if (rndY == snake[i].y && rndX == snake[i].x){
    private function move(e:TimerEvent):void{
    if (left){
    curI -= 1;
    }else if (right){
    curI += 1;
    if (up){
    curJ -= 1;
    }else if (down){
    curJ += 1;
    if (left || right || up || down){
    var s:Sprite = makeItem();
    if (curI > DIM - 1) curI = 0;
    if (curJ > DIM - 1) curJ = 0;
    if (curI < 0) curI = DIM - 1;
    if (curJ < 0) curJ = DIM - 1;
    s.x = grid[curI][curJ].x;
    s.y = grid[curI][curJ].y;
    addChild(s);
    snake.push(s);
    if (Math.floor(s.x) == Math.floor(food.x) && Math.floor(s.y) == Math.floor(food.y) ){
    else if((tmr.currentCount % 3) > 0) { removeChild(snake[0]); snake.shift(); }
    private function changeDir(e:KeyboardEvent):void{
    if(e.keyCode == Keyboard.LEFT) {if (!right){left = true;  up = false; down = false; right = false;}}
    if(e.keyCode == Keyboard.UP) {if (!down) {left = false; up = true;  down = false; right = false;}}
    if(e.keyCode == Keyboard.RIGHT) {if (!left) {left = false; up = false; down = false; right = true;}}
    if(e.keyCode == Keyboard.DOWN) {if (!up) {left = false; up = false; down = true;  right = false;}}
    } </code>
    thanks

    ive added it to the move function and called it in but im getting this error :
                        TypeError: Error #2007: Parameter child must be non-null.
                         at flash.display::DisplayObjectContainer/removeChild()
                         at Snake/move()
                        at flash.utils::Timer/_timerDispatch()
                         at flash.utils::Timer/tick()
    Heres the code that ive changed -
    private function move(e:TimerEvent):void{
    if (left){
    curI -= 1;
    }else if (right){
    curI += 1;
    if (up){
    curJ -= 1;
    }else if (down){
    curJ += 1;
    if (left || right || up || down){
    var s:Sprite = makeItem();
    if (curI > DIM - 1) curI = 0;
    if (curJ > DIM - 1) curJ = 0;
    if (curI < 0) curI = DIM - 1;
    if (curJ < 0) curJ = DIM - 1;
    s.x = grid[curI][curJ].x;
    s.y = grid[curI][curJ].y;
    addChild(s);
    checkForHits();
    if (Math.floor(s.x) == Math.floor(food.x) && Math.floor(s.y) == Math.floor(food.y) ){
    else if((tmr.currentCount % 3) > 0) { removeChild(snake[0]); snake.shift(); }
    private function checkForHits():void {
    for(var i:int=1;i<snake.length;i++){
    if(snake[0].hitTestObject(snake[i])){
    trace("hit")

  • [AS3] Hit detection

    Hello, well I am trying make a game, simple game. It has a movie clip of a bullet, and a shape for a target.
    I am trying to make the bullet hit the target and cause it to register as a hit.
    I had a previous system with just 1 bullet without an array to make more of them, that worked.
    But, this is the error:
    TypeError: Error #1034: Type Coercion failed: cannot convert bullet$ to flash.display.MovieClip.
        at newball_fla::MainTimeline/hitTarget()
        at flash.utils::Timer/_timerDispatch()
        at flash.utils::Timer/tick()
    Here is the code:
    stage.addEventListener(KeyboardEvent.KEY_DOWN, right);
    stage.addEventListener(KeyboardEvent.KEY_DOWN, left);
    stage.addEventListener(KeyboardEvent.KEY_DOWN, space);
    var startbutton = new startButton();
    addChild(startbutton);
    startbutton.x = 400;
    startbutton.y = 350;
    startbutton.addEventListener(MouseEvent.MOUSE_DOWN, onClick);
    var targetTimer:Timer = new Timer(100);
    targetTimer.addEventListener(TimerEvent.TIMER, hitTarget);
    var player:Shape = new Shape();
    player.graphics.beginFill(0x0000FF);
    player.graphics.drawCircle(5, 5, 5);
    player.x = 100;
    player.y = 200;
    addChild(player);
    function onClick(event:MouseEvent):void {
    ball.x = 25;
    ball.y = 55;
    ball.visible = true;
    function right(bmove:KeyboardEvent):void{
    if (bmove.keyCode==Keyboard.RIGHT){
    player.x+= 10
    function left(bmove:KeyboardEvent):void{
        if (bmove.keyCode==Keyboard.LEFT) {
            player.x-= 10
    function space(bmove:KeyboardEvent):void{
    if (bmove.keyCode==Keyboard.SPACE){
    var Bullet:bullet = new bullet();
    targetTimer.start()
    Bullet.x = player.x
    Bullet.y = player.y
    addChild(Bullet);
    Bullet.addEventListener(Event.ENTER_FRAME, moveBullet);
    function moveBullet(e:Event):void{
        e.target.y -=5;
        if(e.target.y <= -10){
            e.target.removeEventListener(Event.ENTER_FRAME, moveBullet);
            removeChild(MovieClip(e.target));
    function hitTarget(event:TimerEvent) : void {
            if(MovieClip(bullet).hitTestObject(ball)) {
            ball.x = 600;
            ball.y = 600;
            ball.visible = false;
            if(MovieClip(bullet).hitTestObject(ball2)) {
            ball2.x = 600;
            ball2.y = 600;
            ball2.visible = false;
    Any help?

    There's a couple of things wrong with the code.  The error you are seeing is partly because you are trying to convert a class (bullet) into a movieclip... not the Bullet you created.  But in the function where you attempt to do that, you don't even have access to the bullets because they are scoped within the function where you create them.
    What you should do is to get rid of the Timer coding altogether and just use the moveBullet function to test for hits since it gets passed the bullet info in its event argument.  Change your moveBullet function to something like...
    function moveBullet(e:Event):void{
        e.target.y -=5;
        if(e.target.y <= -10){
            e.target.removeEventListener(Event.ENTER_FRAME, moveBullet);
            removeChild(MovieClip(e.target));
        } else {
            if(MovieClip(e.target).hitTestObject(ball)) {
               ball.x = 600;
               ball.y = 600;
               ball.visible = false;
           if(MovieClip(e.target).hitTestObject(ball2)) {
               ball2.x = 600;
               ball2.y = 600;
               ball2.visible = false;

  • Detecting Rotation Amount to Control Movie Clips

    I created a movie clip consisting of a bar and a knob.  When you click and drag the knob, the bar rotates through 360 degrees.  I want to be able to detect the degree of rotation and use that metric to control other movie clips.  The code to make the drag/rotate object work is...
    handle.knob.onPress = function(){
    handle.onMouseMove = function(){
      var angle = Math.atan2(this._parent._ymouse-this._y,this._parent._xmouse-this._x);
      this._rotation = angle*180/Math.PI;
      this.knob._rotation = -this._rotation;
      trace(angle);
      trace(angle*180/Math.PI);
    handle.onMouseUp = function(){
    if (this.onMouseMove) delete this.onMouseMove;
    I can trace the angle in radians and degrees but I don't know how to extract either value as a variable that can be used in a function to control a separate movie clip.

    assign a variable to have the value of the _rotation or angle in your onMouseMove function.   and use that variable's value wherever you like.

  • Circles w/o outlines, lines disappear

    I am new to drawing using APsE, so pardon me if this is a stupid question.
    I am having a terrible time drawing a complex segmented circle. The outer circle I got from a file. I then drew 3-pixel black lines dividing the circle into 12 pie-shaped regions.
    Problem 1: I wanted an inner circle that would be transparent fill but have a normal 3-pixel outline. Any circle I draw can have a black or white fill (but not a transparent one), and there doesn't seem to be any way to have the circle edge be black. The menu item Edit/Stroke Outline would seem to be the answer but it is always dimmed.
    Temporary solution: I made the inner circle black-filled, then added another slightly smaller white-filled circle, and moved the latter over the black-filled circle so only the thin black outer edge showed, effectively giving me a circle with a black edge.
    Problem 2: I still needed those 3-pixed lines dividing the inner circle into pie-shaped segments that matched the outer circle. I can draw only 1 pixel-wide lines (wider lines disappear - why is this?), but as soon as I draw a third line the second line disappears. For example, I can draw vertical and horizontal lines, but as soon as I draw a line 30 degrees off-vertical it one of the other lines disappears.
    Temporary solution: None
    I believe I went wrong when I started doing multiple circles. I would have no problem if I could just make an inner circle with the edge showing black but the inside being transparent.
    BTW, I want to then select, in the inner circle, alternating pie shapes and filling them with black. If you see I am going to get into trouble doing that please let me know and offer a solution.
    Thanks. I'm quite good at computers but graphics is like color to a blind person.
    P.S. I am on Windows 7 64-bit SP-1 and Adobe Photoshop Elements 10.0
    EdIsenberg

    Create a new blank image.
    Use the Elliptical Marquee tool to create a large circular selection.
    Use Select...Save Selection to save the selection as "Large Circle".
    Select...Transform selection, and drag one of the corners to make a smaller circle.
    Select...Save Selection to save this as "Small Circle".
    Create a new empty layer.
    Load the large circle selection.
    Stroke the selection with 3px black on the inside.
    Create a new layer.
    Load the small circle selection.
    Stroke it with 3px black on the inside.
    In the Layers Palette, highlight both layers containing stroked circles.
    Choose the Move tool, and in its Options Bar use Align...Vertical Centers, then Align...Horizontal Centers.
    At this point, your image looks like this:
    and your layers look like this:
    Create a new empty layer.
    Use the Line tool and hold down the Shift key to draw a 3px horizontal line filled with black.
    Simplify the line layer.
    Hit Ctrl+J to duplicate the line layer.
    With the Move tool, hold down the Shift key to rotate the copied line 30 degrees.
    Repeat steps 19 and 20 until you have all the line segments drawn.
    At this point your image looks like this:
    and your layers look like this:
    Highlight all the line segment layers, right-click on one of them in the Layers Palette and choose "Merge Layers" to get this layer arrangement:
    On the merged layer, use Select...Load Selection to load the "Large Circle" selection.
    Select...Inverse to invert the selection and hit your Delete key to trim the line segments.
    Deselect All.
    Use Ctrl+Alt+Shif+E (Stamp Visible) to create a new merged layer from all the layers.
    Use the Fill tool on that merged layer to colour to your heart's content.
    The final layers:
    And the final image:
    Added:
    Whooooops!  I see that the line segments aren't centered in the circles.  Add step 24a:
    24a.  Select the layers and use the Move tool's Alignment options to center everything.
    After step 25, you might have to re-align the loaded selection with the image....
    To get the transparency you want in the segments of the inner circle, simply select the segments with the Magic Wand and hit the Delete key, hide all the layers except the top one, then save the image as a PNG:
    Ken
    Message was edited by: photodrawken to add correction.

  • Get "bounds" as a rectangle is rotated

    I have a game with two rectangular sprites that rotate - I need to do some collision detection. The rotation is applied to the sprite image using an AffineTransform which means that once it's drawn getBounds or getWidth/getHeight report the size of the bounding rectangle that my original image is within, not the coordinates of the bit of the image I'm interested in.
    So what I'm trying to do is use some trig to determine the two Areas of each sprite that I'm interested in - the whole body and the "jaws", the bit which is capable of "biting" the other sprite - once I have those Areas I can use Area.intersect() to detect the hit.
    My problem is with the trig - this method is meant to find the four coordinates that track the original "corners" of the image as it's rotated:
    public Area getSpriteZone() {
            int[] pointsX = new int[4];
            int[] pointsY = new int[4];
           //System.out.println(Math.toDegrees(rotation));
            double theta = Math.PI-rotation;
            int offsetX = (int)ORIGINAL_WIDTH/2;
            int offsetY = (int)ORIGINAL_HEIGHT/2;
            int centreX = (int)posX+offsetX;
            int centreY = (int)posY+offsetY;
            int relX1 = (int)(offsetX*Math.cos(rotation));
            int relY1 = (int)(offsetY*Math.sin(rotation));
            //System.out.println("relX: "+relX1+", relY: "+relY1);
            pointsX[0] =  centreX+relX1;
            pointsY[0] =  centreY+relY1;
            int relX2 = (int)(offsetX*Math.cos(rotation+Math.PI));
            int relY2 = (int)(offsetY*Math.sin(rotation+Math.PI));
            pointsX[1] =  centreX+relX2;
            pointsY[1] =  centreY+relY2;
            int relX3 = (int)(offsetX*Math.cos(rotation+(Math.PI*1.5)));
            int relY3 = (int)(offsetY*Math.sin(rotation+(Math.PI*1.5)));
            pointsX[2] =  centreX+relX3;
            pointsY[2] =  centreY+relY3;
            int relX4 = (int)(offsetX*Math.cos(rotation+Math.PI*.5));
            int relY4 = (int)(offsetY*Math.sin(rotation+Math.PI*.5));
            pointsX[3] =  centreX+relX4;
            pointsY[3] =  centreY+relY4;
            return new Area(new Polygon(pointsX, pointsY, 4));
        }for debugging I'm using these coords to draw onto the screen and I can see that it's not bad when the sprite has zero rotation but as it's rotated the method gets less accurate giving a bigger or smaller area than it should. Also, this gives me points in the middle of each of the sides, not the corners. Any ideas?
    see what I mean here: http://jmaid.org/docman/insectRotateZero.png
    and here: http://jmaid.org/docman/insectRotateSome.png
    TIA

    I'm having a go with this but it doesn't seem to be working - I set the Area for the sprite hot Zone when the game begins like this:
    public void setSpriteZone() {
            int[] pointsX = new int[4];
            int[] pointsY = new int[4];
            pointsX[0] = (int)posX;
            pointsY[0] = (int)posY;
            pointsX[1] = (int)(posX + ORIGINAL_WIDTH);
            pointsY[1] = (int)posY;
            pointsX[2] = pointsX[1];
            pointsY[2] = (int)(posY + ORIGINAL_HEIGHT);
            pointsX[3] = pointsX[0];
            pointsY[3] = pointsY[2];
            spriteZone = new Area(new Polygon(pointsX, pointsY, 4));
        }and the game class gets that area with an accessor method. Then in the drawing thread of the game class here's what happens:
    int offsetX = playerImage.getWidth(null)/2;
            int offsetY = playerImage.getHeight(null)/2;
            tx = new AffineTransform();
            tx.translate(player.getX(), player.getY());
            tx.rotate(player.getRotation(), offsetX, offsetY);
            playerZone.transform(tx);//new
            bufferGraphics.drawImage (playerImage, tx, null);drawing the image works fine but my hit detection, which was working with the old, inaccurate Area returned by the trig method, doesn't work now....
    how can I draw the Area onto the screen to get a clue as to what's happening? I looked at PathIterator but don't know how to get the coordinates of the vertices...

  • How do you rotate picture in picture

    I have a picture in picture and I would like to rotate the top video.  I  have figured out how to rotate it 90 degrees, but I don't want it  straight up and down.  I would like to rotate it like 45 degrees, so  that it is at a different angle than the background video.  Is there a  way to do this?  Or will it only rotate in increments of 90 degrees?  (I posted this in the wrong section before, so I hope this is the right place now.)

    Here is my reply to this question, when asked in the Tips & Tricks sub-forum. If anyone has any comments on my method, or a better method, please add them.
    Welcoome to the forum.
    Unfortunately, you have posted to the Tips & Tricks forum, which is a repository for articles on how to do things in PrE and PrPro, and few will see your post here. Hopefully our tireless MOD, Steve Grisetti, will move the post out to the main forum.
    As for Rotation, one of the fixed Motion Effects, like Scale and Position, you can first use the numerical box (to the far right in the Effects>Edit Effects (Effects Control Panel) and either click then type in a value, or click-scrub to change the value. This will be static for your PiP Clip.
    If you wish to Rotate over time, you will want to Keyframe the Rotation Effect, and Rotate Right, or Rotate Left can be chosen. First, opposite Motion, click on the "stopwatch" icon, and you will then see stopwatches appear for all of the fixed Effects. In Rotation, first locate the CTI (Current Time Indicator w/ the red edit line) on the first Frame of your Clip. Click on the stopwatch besides Rotation to add the first Keyframe. Now, move to the last Frame (hitting PageDn, then one cursoe back arrow on the keyboard, will do that for you), and hit the Add Keyframe button on the far right of the Rotation line - looks like a yen-yang diamond, and adjust that Keyframe's value. Note: if you want multiple Rotations, beyond 360 degrees, that is possible, and you will see first a 1, then a 2 (for 2 revolutions).
    Good luck, and hope that helps,
    Hunt
    PS - Steve Grisetti has several great articles on Basic Keyframing on Muvipix.com, plus he's got several wonderful books on PrE, available there. Note: Muvipix, com is a multi-tier Web site, with the forum and some content available just for the free sign-up. Some of the material is available for purchase, or is all free with a subscription. It does not take many paid downloads, before one could have paid for a subscription.

Maybe you are looking for

  • Cannot open iTunes after upgrading it because of computer version

    I just upgraded iTunes to the latest version last night and now it will not let me open due to the fact that I have a Mac Os X 10.4.6 and need 10.4.7 to open iTunes. Is there a way to upgrade the Mac Os X without paying money? If not, can I down-grad

  • Create purchase order form idoc

    Hi everyone, I would be very grateful if someone could explain me whether it is possible to generate a purchase order directly from an incoming ORDERS05 IDOC and specially how to do it. I am receiving an ORDERS05 IDOC from an external system but I do

  • New ledger datasource

    Hi experts, I ‘ve created a Datasource (3FI_GL_xx_TT ) for the new ledger at transaction FAGLBW03. But when I go to RSA3 only the customer include field (ci_cobl) don’t have any data. Do I have to generate extraction structure at FAGLBW01 first? Than

  • Automatic generation of AWR reports

    Hi, How to schedule the automatic JOB to generate the AWR reports hourly basis. ( automatic comparing between 2 snapshots and then generate the text file). Thanks in advance.

  • Customizing Cheque Writer(Generic) to embed xml code and layout

    Hi All, I'm working on International HRMS. I need to customize the seeded Cheque Writer(Generic) Process generated Cheque to embed my layout and print cheques as per our business need. How to do this? Any inputs would help me immensely. Thanks