'플래시'에 해당되는 글 203건

  1. 2010/10/10 플래시 물리엔진 Box2DFlash로 역동적인 모션 그래픽 만들기
  2. 2010/05/22 액체 위에 국기 모양의 공이 떠있는 현상 시뮬레이션 플래시 (2)
  3. 2010/05/17 사실적이고 실감나는 아이폰게임 제작을 위한 즐거운 물리엔진 실험
  4. 2010/03/02 누구나 따라해볼 수 있는 플렉스 애플리케이션 만들기 동영상
  5. 2009/11/11 직장인을 위한 플래시/플렉스 스터디를 추진하겠습니다. (3)
  6. 2009/06/13 소녀시대 맴버들 사진이 3D 방향으로 회전하는 플래시 시계 (5)
  7. 2009/02/23 잘만든 인기 플래시 게임 버블탱크2와 젬크래프트 (16)
  8. 2009/02/15 심심풀이용 플래시 타워 디펜스 게임들과 플레이 동영상 (14)
  9. 2009/01/10 제로보드XE에서 오동작이 생기는 경우 메모
  10. 2008/12/25 참고할만한 7가지 흥미로운 플래시 이펙트 샘플 소스 (26)
  11. 2008/12/17 3일 동안 발행한 홈페이지 정보 오픈캐스트
  12. 2008/10/09 플래시, 외부 파일 데이터 가져오기 통신 샘플 소스 #2 (1)
  13. 2008/10/06 플래시, 외부 파일 데이터 가져오기 통신 샘플 소스 #1 (2)
  14. 2008/10/05 플래시 스터디, 신촌에 있는 미플 스터디 룸을 이용하다. (1)
  15. 2008/10/04 막대 그래프 만들기, 플래시 차트 소스
  16. 2008/10/01 학습용 배너 이미지 슬라이더 플래시 소스 (2)
  17. 2008/09/30 자바스크립트로 아날로그 시계 만들기 (1)
  18. 2008/09/27 클립보드 복사 기능 구현을 위한 소스 코드 (1)
  19. 2008/09/23 초간단 플래시 디지털 시계 만들기 동영상 (15)
  20. 2008/09/22 나만의 아날로그 플래시 시계를 직접 만들어 보자. (4)
  21. 2008/09/21 플래시 스터디, 세로형 네비게이션 만들기 (2)
  22. 2008/09/05 무료로 쓸만한 플래시(SWF)와 FLV 동영상 플레이어 (5)
  23. 2008/08/24 플래시(Flash) 스터디와 플렉스(Flex) 스터디
  24. 2008/07/16 IT 관련 스터디 및 세미나실 행사장 참고자료.
  25. 2008/06/16 자유로운 메시지 교환을 위한 플래시톡(Flash Talk). (7)
  26. 2008/06/15 플래시 액션 스크립트 3.0, 고성능 3D 데모 (6)
  27. 2008/06/08 심플한 플래시 투표 위젯, TOP10 (8)
  28. 2008/04/13 웹브라우져 시작페이지를 가볍고 깔끔하게... (1)
  29. 2008/02/10 소녀시대 프로필 플래시 갤러리. (4)
  30. 2008/02/08 슈퍼마리오 브라더스 에뮬 게임과 플래시 게임
위키백과에서는 물리엔진을 다음과 같이 설명하고 있습니다.
물리 엔진 또는 물리 연산 엔진은 강체동역학(충돌 감지 포함), 연체동역학, 유동역학과 같은 단순한 특정 물리 시스템을 최대한 시뮬레이션하려고 하는 컴퓨터 소프트웨어이다. 이 엔진은 컴퓨터 그래픽스, 비디오 게임, 영화 분야에 쓰인다. 주로 비디오 게임에 미들웨어로서 이용되며 실시간으로 시뮬레이션 처리한다. 이 용어는 고성능 과학 시뮬레이션과 같은 물리 현상을 시뮬레이션하기 위한 소프트웨어 시스템을 가리키는 데 쓰이기도 한다.
Box2D는 다양한 개발언어에서 활용될 수 있는 2D 물리엔진이며 이를 실습해보기 위해 플래시 물리엔진 Box2DFlash 를 활용해서 간단하지만 역동적인 모션 그래픽을 만들어보았습니다. 중력과 마찰력을 없애고 탄성을 적당히 셋팅하면 다음과 같은 영상이 만들어집니다.




웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/619

댓글을 달아 주세요

물리엔진으로 실감나는 생생한 플래시 게임을 만들어 보려고 이런 저런 테스트 중에 부력 시뮬레이션도 테스트 해볼 수 있게 되어 간단한 동작을 하는 플래시를 빌드해봤습니다. 하단에 놓여진 유체 위에서 부력이 작동하여 그 위에서 공이 떠있는 현상을 테스트 한 것입니다. 공에는 여러나라 국기의 모습이 입혀져 있으며 처음에는 20개의 공이 한꺼번에 떨어지며 3초 간격으로 추가로 공이 한개씩 떨어지도록 되어 있습니다. 그리고 떨어진 공들은 마우스로 드레그해서 움직일 수 있습니다. 유체 위에 공이 떨어지면 유체가 출렁이는 현상이 생기면 좋겠다는 아쉬운 부분도 있어 약간의 이펙트를 줘서 개선해 보면 좋을 것 같다는 생각도 들고 약간의 규칙을 적용해서 게임을 만들어 보면 어떨까 하는 생각도 해보게 됩니다.
부력 테스트를 위해 Box2DFlash 물리엔진과 b2BuoyancyController 를 사용했으며 물리엔진에 관심있는 분들은 관련 샘플 소스를 참고해서 개성있는 플래시 제작에 활용해보시기 바랍니다. 물리엔진을 처음 접하시는 분들은 관련 메뉴얼을 먼저 읽어보셔야 할 것이며 함께 포함된 예제 소스를 실행해보시면 도움이 될 것입니다.

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/614

[연관 포스트]
아이폰 게임 제작을 위한 2D 그래픽 엔진 Cocos2D 설치 및 실행 동영상
아이폰 아이팟 코코아 터치 애플리케이션 개발 샘플 동영상
직장인을 위한 아이폰 게임 디자인 스터디를 추진해 봅니다.
직장인을 위한 아이폰 앱 개발 Cocos2D 스터디를 추진합니다.

댓글을 달아 주세요

  1. 이키루공공 2010/06/23 21:29  댓글주소  수정/삭제  댓글쓰기

    box2d...귀에만 익은 이름이네요. 좋은 예제도 있으니..잘 공부하겠습니다 트위터로 퍼갔습니다 ^^

  2. 세이지클라서 2010/05/22 11:36  댓글주소  수정/삭제  댓글쓰기

    와... 엄청 신기하네요.,. 이런걸 플래시로도 만들 수 있군요..

최근에 관심을 가지고 다뤄보고 있는 게임 개발을 위한 물리 엔진 Box2D를 활용해서 사실적이고 실감나는 아이폰 게임을 만들어 보려고 준비하고 있습니다. 박스2D는 다양한 개발 플렛폼으로 포팅 되어 있어 그래픽 툴로 많이 활용되고 있는 플래시에서도 작업해볼 수 있습니다. 그래서 간단한 테스트는 플래시와 액션스크립트를 활용해보고 있고 차후 아이폰  게임 개발과 동시에 플래시 게임도 개발해 볼 수 있을 것 같네요. 아래 보여지고 있는 플래시에서는 물리엔진으로 Box2DFlash 를 사용했고 b2MouseJoint, b2DistanceJoint, b2PrismaticJoint, b2PulleyJoint, b2RevoluteJoint, b2GearJoint 가 테스트 되었습니다. 관심 있는 분은 출력되고 있는 도형을 마우스로 드래그 해서 움직여 보세요. 플래시를 보면 대략 짐작하시겠지만 물리엔진을 다루는 것은 물리와 수학에 대한 개념도 필요한 섬세한 작업이므로 차분하고 끈기 있는 관심과 노력이 필요할 것 같습니다. 비교적 다루기 어려운 주제이지만 시각적인 즐거움을 주는 주제이므로 재미있습니다.


웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/612

[연관 포스트]
아이폰 게임 제작을 위한 2D 그래픽 엔진 Cocos2D 설치 및 실행 동영상
아이폰 아이팟 코코아 터치 애플리케이션 개발 샘플 동영상
직장인을 위한 아이폰 게임 디자인 스터디를 추진해 봅니다.
직장인을 위한 아이폰 앱 개발 Cocos2D 스터디를 추진합니다.

댓글을 달아 주세요

이 전에 포스팅한 "아이폰 아이팟 코코아 터치 애플리케이션 개발 샘플 동영상" 게시물에서 소개하고 있는 아이폰 애플리케이션과 비슷한 기능을 하는 플렉스 애플리케이션을 만드는 과정을 동영상으로 캡쳐해봤습니다. 우리가 알고 있는 플래시를 좀더 손쉽고 체계적으로 개발 할 수 있게 해주는 플렉스 프레임워크를 활용하면 비교적 적은 노력으로 유저 인터페이스를 좀더 세련되게 제작할 수 있게 됩니다. 동영상에는 플렉스 빌더가 등장하며 디자인 모드에서 라벨(Label)과 버튼(Button) 컨트롤을 플렉스 애플리케이션 컨테이너 위에 올리고 이 버튼을 클릭하면 웹브라우져로 어도비(Adobe) 홈페이지를 여는 매우 간단한 프로그램을 만드는 과정을 영상으로 담은 것입니다. 드림위버 같은 툴로 HTML과 자바스크립트를 다루는 느낌과 유사해 보이지만 실제 개발을 하기 위해서는 훨씬 많은 학습이 필요합니다.



웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/596

댓글을 달아 주세요

직장인을 위한 플래시/플렉스 스터디를 추진하려고 합니다. 액션스크립트 3.0을 다뤄야 하니 개발 경험(언어 무관)이 있어야 하고 프로그래밍에 관심이 있는 분들이 참여해야 하겠습니다. 스터디 장소는 서울(합정동)에 있는 사무실(회의실)이 될 것이므로 서울 근교에 계신 분들이 좋겠고 가용한 컴퓨터가 없는 관계로 개인 노트북이 필요합니다. 주말(토/일요일)을 활용할 것이며 참가 맴버간 합의가 된다면 주중 야간 시간대도 이용하게 될 수 있습니다. "한 번 해볼까?"라고 생각하는 분이면 곤란하며 적극적으로 참여 가능한 분이면 좋겠습니다. 필수 사항은 아니지만 이왕이면 아이폰/아이팟 어플 개발에 관심 있는 분이면 더 좋겠습니다.
참여 가능한 분들은 일단 댓글 남겨주시고 개발 경험이나 실무 경험에 관련된 간단한 자기 소개와 연락처(이메일,메신져,연락처)가 담긴 이메일(hompy @ live . com) 보내주세요. 그러면 검토 후에 답장 드리겠습니다. 다만 스터디 장소가 넓지 않은 관계로 인원제한이 필요하므로 선택적으로 답장을 보내드리도록 하겠습니다.
참가 신청 상황에 따라 신청자 여러분들끼리 또다른 팀을 구성하셔도 좋겠습니다.
참가자가 확정되면 구체적인 스터디 추진 방향을 결정하기 위한 가벼운 형식의 모임을 하겠습니다.
참가자 분들이 나름대로 자신의 업무에 바쁜 직장인들이 될 것이므로 수동적인 참여 보다는 능동적으로 참여했으면 하며 서로의 스캐쥴을 위해 시간 약속을 개념있게 지켜주시는 분들이길 바랍니다. 스터디 진행시 별도의 비용은 발생하지 않을 것이나 학습에 필요한 노트북이나 관련 책자 등은 스스로 준비하면 될 것입니다. 본 스터디는 전문적인 강사가 일방적으로 강의 해주는 방식이 아니므로 주의해주시고 공통의 관심사에 대해 스터디도 하고 비슷한 일을 하는 분들이 정보 교환도 하며 필요하면 서로의 인맥도 되어줄 수 있는 뜻 있고 유익한 자리가 되도록 함께 했으면 합니다.
함께 하고 싶은 분은 지금 바로 이메일 주세요.

http://cug.kr/1Iw

댓글을 달아 주세요

  1. 웹프로그래머 2009/11/23 14:05  댓글주소  수정/삭제  댓글쓰기

    현재 첫번째 스터디 그룹 맴버 구성은 총 7명으로 조직 완료 되었고 두번째 스터디 그룹 맴버 구성을 검토하고 있습니다. 관심 있으시면 아래 게시판 링크를 통해 스터디 그룹에 참여하고 싶어 하는 다른 분들을 확인하실 수 있습니다. 그리고 두번째 스터디 그룹을 이끌어 주실 분이 나타난다면 빠르게 스터디 조직이 가능할 것입니다.
    http://www.flashcafe.org/basic_study
    플래시카페 > 홈 > 커뮤니티 > 플래시스터디
    이 게시판은 닫힌 게시판으로 운영하고 있으며 로그인 하시면 내용을 확인할 수 있습니다.

  2. 혜승아빠 2009/11/23 10:42  댓글주소  수정/삭제  댓글쓰기

    오호..이거 아직도 모집하시려나?

  3. 서유미 2009/11/13 17:35  댓글주소  수정/삭제  댓글쓰기

    좋은 시간이 될것 같습니다.~~~

플래시 CS4 툴을 이용해서 3D 좌표 속성을 주기적으로 변경하여 소녀시대 맴버 사진들을 입체적으로 회전시켜보는 간단한 플래시 시계를 만들어보았습니다. "내 사진으로 만드는 재미있는 플래시 시계"라는 포스트에서 소개한 플래시를 약간 개조한 것입니다. 재미삼아 취미로 사용했던 플래시를 오랜만에 다뤄보려니 새롭게 습득해야할 것들이 많아졌군요. 당분간 플래시에 시간 투자를 해야할까봐요.


addEventListener(Event.ENTER_FRAME, rotate_movieclip);
function rotate_movieclip(event:Event):void {
    mc_box.rotationY+=2;
    //mc_box.rotationX+=3;
    mc_box.rotationZ+=1;
}

<embed src="http://www.hompydesign.com/flash/3dclock.swf" quality="high" width="240" height="240" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"></embed>

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/578

댓글을 달아 주세요

  1. 얼음사랑 2009/11/09 19:31  댓글주소  수정/삭제  댓글쓰기

    그림이 바뀌면서..멋있습니다.

  2. 외톨이 2009/09/17 19:10  댓글주소  수정/삭제  댓글쓰기

    안녕하세요

  3. 윤광영 2009/09/12 17:25  댓글주소  수정/삭제  댓글쓰기

    와-_-;;; 멋지시다

  4. 피노키오 2009/06/20 14:44  댓글주소  수정/삭제  댓글쓰기

    이글은 태그공개 안해주시나바용 ㅠ_ㅠ

  5. 비밀방문자 2009/06/15 11:54  댓글주소  수정/삭제  댓글쓰기

    관리자만 볼 수 있는 댓글입니다.

아래 동영상은 모 플래시 게임 사이트의 TOP5에 드는 인기 플래시 게임 버블 탱크와 젬크래프트 를 실행해본 동영상입니다. 버블 탱크는 위,아래,좌우를 돌아다니며 버블로 만들어진 적을 소탕하는 슈팅 게임입니다. 적을 제거하면 잔여 버블이 생기는데 이 버블들을 모으면 내 버블 탱크의 능력을 높일 수 있는 레벨업이 가능합니다. 마우스와 키보드를 동시에 조작해야 하며 마우스로 적을 겨냥하고 클릭하여 제1무기를 발사 할 수 있고 기본 설정인 [W], [S], [A], [D] 키로 이동 할 수 있고 [SPACE] 키로 제2무기를 발사할 수 있습니다. 이동하면 할수록 다양한 무기로 무장한 덩치가 크고 파워가 강한 적이 등장하고 이로 인해 압도 되어 긴장감이 고조됩니다. 아래 동영상을 보시면 어떤 게임인지 대략 가늠할 수 있을 것이며 동영상 위에 있는 링크를 이용해 게임을 실행할 수 있습니다.

[bubble tanks 2]
http://www.hompydesign.com/game/bubbletanks2.php
 

젬크래프트는 잘만든 플래시 타워 디펜스게임중에 하나로 다양한 기능을 하는 보석을 결합하고 배치하여 끊임 없이 진격하는 좀비들을 제거해야 하는 게임입니다. 좀비를 제거하면 마나가 쌓이는데 이를 이용해 보석을 획득하고 조합할 수 있고 때로는 보석을 던져 폭탄으로 쓸 수 있습니다. 또한 마나를 소비해서 장애물도 만들 수 있고 마나의 최대치도 높일 수 있지요. 48개의 레벨이 있으며 마지막 레벨까지 도달하는데 꽤나 많은 게임 플레이 시간이 필요합니다. 레벨을 높이는 것이 중반이후로 쉽지 않으므로 색깔별 보석의 특성을 잘 파악하고 이를 잘 조합해서 필요한 만큼의 보석을 배치하고 이동해서 파워를 집중하고 극대화 하는 것이 중요하다고 볼 수 있습니다. 역시 아래 게임 플레이 동영상으로 대략의 게임 방법을 파악하고 게임을 즐겨보세요. 참고로 아래 동영상은 치트엔진으로 마나핵과 스피드핵을 해서 좀더 수월하게 마지막 미션을 완수하는 동영상입니다. 게임실행은 동영상 위에 있는 링크를 이용하세요.

[gemcraft]
http://www.hompydesign.com/game/gemcraft.php
 

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/570

댓글을 달아 주세요

  1. 비밀방문자 2010/07/29 02:57  댓글주소  수정/삭제  댓글쓰기

    관리자만 볼 수 있는 댓글입니다.

  2. 흠... 2010/03/16 15:31  댓글주소  수정/삭제  댓글쓰기

    이런 게임을 이제서야 알게되다니...ㅠ_=)젬크래프트 원 93렙찍고 목표 경험치 초과하고 2억9천만점 찍는동안 느낀 치명적인 힌트 하나 드리자면 스피드가 생명이네요..단축키가 괜히 있는게 아니었음; 렙 높은 보석 스킬 다 찍은 다음부터 7렙 보석 몇개만 깔아두고 스피드3배 찍고 웨이브 열심히 돌리고 열심히 마나통 찍고 낮은 보석은 폭탄 써주고 하면서 달리면 되겠습니다- 아뮬렛 목표 달성하면 보너스 점수도 있는 것 같습니다.

  3. aa 2010/02/09 10:00  댓글주소  수정/삭제  댓글쓰기

    젬 제일 좋은게 보라색

    노란색보다 더 효율적이고 속도가 더빠름

  4. 아이콘봉 2010/01/27 09:09  댓글주소  수정/삭제  댓글쓰기

    젬... 올 클리어... 랭크 83, 아뮬릿 모두 획득, 스코어 248,254,740 , 최대 포인트 930만... 초반 마나 통 키우시길... 그럼 쉽게 끝납니다.

  5. gem 2009/11/02 21:53  댓글주소  수정/삭제  댓글쓰기

    젬크레프트에 총 마나 보유량과 획득량 늘리는거 자주 사용하시면 목표 경험치(파란색)까지 금방 올리더 군요. 그리고 전 2개씩 짝을 지어서 듀얼을 주로 사용해요. 하나씩 만들다 보면 색이 잘 안맞아 힘들더군요

  6. 치트엔진신기하군요 2009/09/28 21:30  댓글주소  수정/삭제  댓글쓰기

    저번에 받긴했는데 사용방법이랑 플래시게임을 받아서 해야하나요??

  7. 치트좀알려주세요 2009/09/16 02:11  댓글주소  수정/삭제  댓글쓰기

    치트어케쓰죠???

  8. 치트좀알려주세요 2009/09/16 02:11  댓글주소  수정/삭제  댓글쓰기

    저기 치트 어케쓰죠?ㅠ

  9. 타워디펜스 2009/09/05 23:12  댓글주소  수정/삭제  댓글쓰기

    타워 디펜스 진짜 군대에있을때 많이했는데

    지겹도록한게임ㅠ

  10. 두겜다 2009/04/12 11:47  댓글주소  수정/삭제  댓글쓰기

    쩝.. 거의 댓글 도배..수준이네 -_-;; 한가지만 더 팁.. 스킬 초기화를 잘 활용하세요. 중/하위보석, 듀얼마스터리 같이 별 필요 없는 스킬은 올리지 마시고 상위보석, 젬이랑 건물 싸게하는거, 합치기 싸게하는거, 마나리젠, 마나테이크 같이 필수적인것에만 집중 투자하세요. 이정도만 신경쓰시면 47스테이지까지는 무난히 클리어 가능합니다. 48 스테이지는.. 약간의 운도 따라줘야해서 =_=;;; 저도 어쩌다 실패하곤 합니다.

  11. 두겜다 2009/04/12 11:40  댓글주소  수정/삭제  댓글쓰기

    참고로 제가 가장 추천하는 보석은 Red랑 Lime, Yellow예요. Red는 스플래시 데미지고, Lime은 체인이라고 해서 일정 확률로 앞 뒤에 있는 녀석들을 연달아 때리죠. Yellow는 일정 확률로 3배 데미지구요. 물론 전 Red를 제일 선호합니다. 스테이지별 요령이라고 하긴 좀 뭐하지만, 화면 왼쪽에 좀비들 나오는 게이지 있죠? 최대한 그걸 활용하세요. 그냥 가만히 있으면 시간은 벌 수 있어도 그걸 눌러서 다음 턴 녀석들이 일찍 나오게하면 경험치와 마나를 줍니다. 그걸 최대한 이용하는거죠. 이럴 때 Red보석이 좋아요. Red는 애들이 뭉치면 뭉칠수록 효율이 좋거든요. 최대한 Red나 Lime을 많이 뽑아서 Pure를 만드시고 나머지는 그냥 섞어도 상관 없어요. Yellow는 보스몹에게 나름 유용해요. 범위도 넓고 연사속도도 빠른편인데다가 3x 한방 터지면 제법 통쾌하죠.

  12. 두겜다 2009/04/12 11:33  댓글주소  수정/삭제  댓글쓰기

    젬크래프트의 경우엔 경험치를 모으는게 중요한데, 한번 깬 판이라고 무시하지 마시고 스킬을 얻은 다음 다시 도전해서 경험치를 더 얻어보세요. 그리고 한판 깰 때마다 스테이지 그림 겉에 파란 줄 같은게 차 오르는게 보이실텐데, 그게 그림 끝까지 올라가면 푸른배경이 생겨요. 일정 구역을 전부 그렇게 만들면 숨겨진 스테이지가 나타납니다. 경험치도 올리고 히든스테이지도 볼 수 있다는거죠.

  13. 두겜다 2009/04/12 11:28  댓글주소  수정/삭제  댓글쓰기

    버블탱크2의 경우 파이터계열로 업그레이드 하시다가 스나이퍼의 최종형인 고스트 스나이퍼까지 가면 그리 어렵지 않게 클리어 하실 수 있을겁니다. 이동속도도 제일 빠른데다가 일단 몸집이 작아서 피하기가 쉽고, 탄환이 한발씩 나간다곤 해도 스플래시 판정이 있어서 일단 맞기만 하면 어지간한 녀석들은 2~3방에 다 해결 됩니다.헤비 계열로 가면 파워가 좋다고는 하지만 너무 움직임이 둔하고 몸집도 커서 컨트롤은 커녕 기껏 모아놓은 버블 다 잃어버리기 일쑤죠.

  14. 버블탱크클리어!! 2009/03/24 08:46  댓글주소  수정/삭제  댓글쓰기

    휴.. 40분의 사투 끝에 클리어를 했네요.ㅋ
    버블탱크2클리어//축하여~

  15. 얼음동자 2009/03/12 23:07  댓글주소  수정/삭제  댓글쓰기

    헐.. 젬크래프트 검색하다가 이곳에 오게됐네요..
    지금 30판인데.. 헐.. 너무 어렵네요..
    치트 없이 깨시는 분들은 정말 대단하신듯..
    전략이 잘못됐는지.. 중반 이후 너무 힘들어진다는...
    좋은 전략이 있으면 좀 알려주세요~

  16. 버블탱크2클리어 2009/02/27 20:16  댓글주소  수정/삭제  댓글쓰기

    후.. 드디어 다꺳네요~

무료한 시간을 달래기 위해 간편하게 즐길 수 있는 심심풀이용 플래시 타워 디펜스 게임들을 플레이한 동영상들입니다. 개별 디펜스 게임을 직접 실행보려면 플레이 동영상 상단 링크를 열어보면 됩니다. 대부분의 게임 들은 치트엔진으로 머니핵을 해서 어떤 강력한 타워들을 배치할 수 있는지 알아보았습니다. 플래시 써클 디펜스와 앤트버스터 게임은 파이널 레벨이 없이 무제한으로 진행되는 게임으로 보이고 이 게임들은 머니핵으로 무제한으로 타워를 구입하고 레벨업을 하더라도 좀비들의 체력이 기하급수적으로 늘어나서 400 레벨 이상 가기 어려운 것 같습니다. 동영상을 보시면 개별 게임의 특징을 대략 파악해볼 수 있을 것이나 각 게임마다 특색도 있고 게임 방식도 약간 다르며 게임 그래픽의 퀄리티도 다르므로 여가 시간을 이용해 플레이해보세요.^^

[canyon flash defense game]
http://www.hompydesign.com/game/canyontd.php


[ant buster tower defense game]
http://www.hompydesign.com/game/antbuster.php


[defender hold thd holy pig flash defense game]
http://www.hompydesign.com/game/defenderholdthepig.php


[vector td 2 flash defense game]
http://www.hompydesign.com/game/vectortd2.php


[vector td x flash defense game]
http://www.hompydesign.com/game/vectortdx.php

[temple guardian flash defense game]
http://www.hompydesign.com/game/templeguardian.php


[onslaught2 flash defense game]
http://www.hompydesign.com/game/onslaught2.php


[elite forces defense game]
http://www.hompydesign.com/game/eliteforces.php


[flash circle defense game]
http://www.candystand.com/play.do?id=17995


웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/569

댓글을 달아 주세요

  1. 이런.. 2010/05/16 23:25  댓글주소  수정/삭제  댓글쓰기

    왜 매드니스 컴뱃 디펜스는 없는가?!!

  2. zzz 2010/03/08 23:10  댓글주소  수정/삭제  댓글쓰기

    첫번째 동영상 그건 버그 안써도 엄청 쉽고 3가지 헬?모드 엄청쉽고 재밋고^^
    아시운점은 마지막단계가 있다는거.. 애써서 해놧는데 끝.. 더 하고 싶엇는데 ㅋㅋㅋ

  3. 우와라 2010/03/07 23:51  댓글주소  수정/삭제  댓글쓰기

    ㅋㅋㅋㅋ 치트라서 그런지...쉬운데..개미 레벨 90 2만이 넘네체력이,,,쩝,,디게 저러 ㅋㅋㅋㅋㅋ

  4. 와우 2010/03/07 16:55  댓글주소  수정/삭제  댓글쓰기

    저거 버그도 있었나?

  5. ㅋㅋㅋㅋ 2010/03/06 12:20  댓글주소  수정/삭제  댓글쓰기

    쇼미더머니레 ㅋㅋ

  6. 버그 2010/02/26 14:57  댓글주소  수정/삭제  댓글쓰기

    개미버그 저 링크 들어가서 오른쪽에 있는 [show me the money] 하면됨

  7. 아놔 2010/02/26 14:55  댓글주소  수정/삭제  댓글쓰기

    개미 le:89 체력 19320 ㄷㄷㄷ

  8. ㅋㅇㄹ 2010/01/28 17:22  댓글주소  수정/삭제  댓글쓰기

    [vector td x flash defense game]

    읔.. 저거 도저히 안깨져서 동영상 보고 공략 따라할랬는데..

    치트키군요 -0-; ㅋㅋ

    44레벨정도에 모든 타워 10단계에.. 도배를 해버리네 ㅋㅋ

  9. ... 2010/01/26 23:43  댓글주소  수정/삭제  댓글쓰기

    별걸다하셧네요 ㅋㅋ 저거중에 3개는 해봣음..

  10. 뭥미.. 2010/01/26 11:56  댓글주소  수정/삭제  댓글쓰기

    개미타워 버그 뭥미...

  11. dlawowoowow 2009/03/22 11:03  댓글주소  수정/삭제  댓글쓰기

    개미버그어떻게써여?

  12. manijang2 2009/02/17 03:35  댓글주소  수정/삭제  댓글쓰기

    ant buster 버그 이용한거네요.. =_=;; 얼마나 잘할까 했더니... 수정 바람니다.

  13. 아크몬드 2009/02/15 23:33  댓글주소  수정/삭제  댓글쓰기

    개미, Desktop Tower Defence는 해봤습니다.

간단하게 커뮤니티를 만들어 보기 위해 제로보드XE와 얼마전 업그레이드 하면서 새로운 이름으로 변경된 XpressEngine을 설치해서 사용해 보았습니다. 다양한 기능이 장점이지만 그로 인해 초급자의 경우 사용하기에 다소 복잡한 면이 있어 보입니다. 쓰다보니 PHP 설정 파일에 always_populate_raw_post_data 의 값을 On 상태로 해놨을 경우 원하는 페이지가 나오지 않고 아래와 같은 오동작을 일으키는 경우가 있어서 참고할 수 있도록 기록으로 남겨둡니다.
XMLSocket 을 이용해 플래시에서 XML 형식으로 PHP 와 통신하기 위해 이 설정을 켜두고 $HTTP_RAW_POST_DATA 변수를 통해 플래시에서 보내온 XML 데이터를 받아서 PHP 로 파싱한 후에 사용했었습니다.

[오동작 결과]
- <response>
    <error>0</error>
    <message>success</message>
  </response>

[/etc/php.ini 설정]
always_populate_raw_post_data = On

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/560

댓글을 달아 주세요

여러가지 흥미로운 플래시 이펙트입니다. 플래시 인트로나 플래시 네비게이션 등에 응용하면 유용할 것 같습니다. 아래 소개된 플래시 소스를 참고할 수 있도록 플래시 소스 묶음 파일도 첨부합니다.

[플래시 소스, 폭죽 터지는 효과]


[플래시 소스, 텍스트 이펙트]



[플래시 소스, 불꽃 제어]



[플래시 소스, 잡고 던질 수 있는 매직볼]
마우스로 볼을 잡고 던지기.


[플래시 소스, 전기 방전 효과]



[플래시 소스, 웨이브 에뮬레이션]
마우스로 중앙에 있는 네모를 잡고 흔들기.


[플래시 소스, Cyber, Gypnotic 이펙트]



[플래시 소스 모음]


웹프로그래머의 홈페이지 정보 블로그 http://hompy.info/550

댓글을 달아 주세요

  1. 티박스 2011/12/28 14:04  댓글주소  수정/삭제  댓글쓰기

    와우 멋지네요 감사히 가져가겠습니다~!

  2. 소현 2010/12/20 05:32  댓글주소  수정/삭제  댓글쓰기

    짱입니다요.. 유용하게쓸게여..!!!
    혹시 대답해주실수있나요 궁금한게있는데!,
    플래시에서 사진업로드하는 소스작성하려면 어떤식으로해야할까요..

    사진업로드한걸로 퍼즐맞추는 플래시하려고하거등영...
    답변주실수있음 주세여^^ a_akwon@lycos.co.kr
    무튼 좋은 자료담아갑니다.

  3. dr 2010/11/24 18:50  댓글주소  수정/삭제  댓글쓰기

    아래 예기치 않은 파일이라구 뜨시는 분들~
    플래시의 버젼이 낮아서 그렇습니다

  4. 양마니 2010/10/20 13:54  댓글주소  수정/삭제  댓글쓰기

    오우~~

  5. charlie 2010/04/10 12:31  댓글주소  수정/삭제  댓글쓰기

    와아우 감사해요

  6. 우와우 2010/04/05 10:22  댓글주소  수정/삭제  댓글쓰기

    대단합니다 와아우 감사해요~ 데려갑니다요!

  7. 서미조치 2010/01/02 17:10  댓글주소  수정/삭제  댓글쓰기

    첨 와봤는데 참 신기하네요.

  8. 엘리트 2009/12/11 22:24  댓글주소  수정/삭제  댓글쓰기

    감사히 담아갑니다.

  9. tana 2009/11/26 17:23  댓글주소  수정/삭제  댓글쓰기

    감사합니다... 좋네요..
    근데 폭죽만 없네요.. 당장 이게 제일 필요한데.. 아깝다;;

  10. RIA 2009/11/16 18:09  댓글주소  수정/삭제  댓글쓰기

    이게.. 플래시인가요....?? 대단해요....
    플래시잘해서 뭐하나좀해보자 라는생각가지고있는데..
    전 정말 심각하게 먼거같아요ㅠㅠ 데려갑니다!

  11. 몽실몽실 2009/10/22 18:05  댓글주소  수정/삭제  댓글쓰기

    멋진데요 담아가겠습니다

  12. 오오..가저갑니다 2009/09/06 07:49  댓글주소  수정/삭제  댓글쓰기

    Thanks....

  13. 박두현 2009/08/25 09:08  댓글주소  수정/삭제  댓글쓰기

    멋진 이펙트 고맙습니다.

  14. 계순이 2009/07/19 21:47  댓글주소  수정/삭제  댓글쓰기

    너무 유용한 정보 감사합니다. 잘보았습니다.

  15. 2009/07/10 16:49  댓글주소  수정/삭제  댓글쓰기

    텍스트 멋있네요.. 꼭 써먹어야지..^^ 감사해요

  16. 붉은머리 2009/07/09 16:06  댓글주소  수정/삭제  댓글쓰기

    대단하십니다. 정말 멋지네요~!!

  17. 박시원 2009/06/30 16:11  댓글주소  수정/삭제  댓글쓰기

    정말 멋져요!!!
    대단합니다. 꼭 이거 다 만드는것에 도전해볼께요 감사해요~~!!
    눈이 맑아지는 느낌 ㅋㅋㅋ

  18. 김호덕 2009/06/10 23:16  댓글주소  수정/삭제  댓글쓰기

    늦은나이에 플래시에 입문해서 요즘 많이배우고있습니다.
    이렇게 좋은 정보를 공유해 주셔서 감사합니다.

  19. ug-hwan 2009/04/08 13:42  댓글주소  수정/삭제  댓글쓰기

    thanks a lot

  20. dhtmdgus5072 2009/03/28 17:54  댓글주소  수정/삭제  댓글쓰기

    와우 짱이에요.

  21. 세바 2009/03/23 21:50  댓글주소  수정/삭제  댓글쓰기

    저도 제이준님과 같은데요.
    어떻게 하면되죠?
    ysic0323@naver.com

  22. 제이준 2009/03/18 07:26  댓글주소  수정/삭제  댓글쓰기

    텍스트 이펙트만 따로보내주시면 안될까여? rlawpwns23@naver.com
    이리로여~ 부탁드려여

  23. 제이준 2009/03/17 09:27  댓글주소  수정/삭제  댓글쓰기

    근데 저는 예기치않은 파일이라구 텍스트 이펙트파일이 안떠여 ㅠㅠㅠ

  24. KIMICOM 2009/03/09 09:25  댓글주소  수정/삭제  댓글쓰기

    Thanks a lot

  25. 이드 2009/02/27 06:27  댓글주소  수정/삭제  댓글쓰기

    우와... 컴퓨터 잘하는 분든은 정말 부럽네요 ㅜ.ㅜ

  26. 도트 2009/02/08 08:44  댓글주소  수정/삭제  댓글쓰기

    대단하네요~ 퍼가요^^

네이버 오픈 캐스트가 런칭한 이후로 3일동안 총 7개의 정보 꾸러미를 발행했습니다. 블로그에 있는 글 중에 유익하다고 판단되는 글들을 선별해서 묶어둔 것을 4회에 걸쳐 발행했고 이후 3회 동안 웹개발 관련 유익한 홈페이지들을 소개하는 정모 묶음으로 구성하였습니다. 앞으로도 "홈페이지 정보" 라는 주제에 걸맞는 다양한 정보 꾸러미들을 발행할 생각입니다. 본 캐스트에 관심이 있는 분들은 아래 링크를 클릭하신 후 관련 내용을 확인할 수 있으며 캐스트를 감상해보시고 필요하다고 느끼시면 구독 바랍니다.^^
http://opencast.naver.com/IT243








웹프로그래머의 홈페이지 정보 블로그 http://hompy.info

댓글을 달아 주세요

플래시로 외부 파일 데이터를 가져오기 위한 웹서버와 통신하기 두번째 샘플 소스 코드입니다. 플래시 액션스크립트 초급자를 위해 학습용으로 부담없이 테스트할 수 있도록 만들었으므로 차근 차근 살펴 보시면 이해에 도움이 될 것이라 생각됩니다. 아래 예제 처럼 LoadVars 객체를 이용해서 통신을 하는 것이 먼저 소개해드렸던 XML 객체를 이용하는 것 보다는 좀더 손쉽게 사용될 수 있습니다. 그러나 전달해야할 데이터가 복잡한 구조를 가질 경우 XML 객체를 이용하는 것 보다 혼란스러울 수 있으며 눈으로 손쉽게 데이터를 해석하기 어려울 수 있습니다. 아래 제공하는 샘플 소스 코드를 필요에 맞게 수정하고 개선해보면 어떻게 사용하는 것인지 이해하기 쉽습니다. 잘 익혀두었다가 사용자의 데이터를 등록하고 갱신하는 응용 프로그램 모양의 플래시를 만드는데 활용해보세요.

[product.txt]
title=system&attribute=name|price|total|date&product=desktop|380000|10|2008-10-01,monitor|270000|5|2008-10-04,printer|160000|2|2008-09-28,notebook|870000|15|2008-10-06,mouse|12000|20|2008-09-20

[product_txt.fla]
System.useCodepage = true;
var product_vars = new LoadVars();
product_vars.onLoad = function(success) {
    if (success) {
        var attribute_str = this.attribute;
        var product_str = this.product;
        var attribute_array = this.attribute.split('|');
        var tmp_array = product_str.split(',');
        var product_array = [tmp_array[0].split('|'), tmp_array[1].split('|'), tmp_array[2].split('|'), tmp_array[3].split('|'), tmp_array[4].split('|')];
        tf_textarea.text += '[text file tester]\n';
        tf_textarea.text += '01: ' + this.title + '\n';
        tf_textarea.text += '02: ' + this.attribute + '\n';
        tf_textarea.text += '03: ' + this.product + '\n';
        tf_textarea.text += '\n';
        tf_textarea.text += '04: ' + this.attribute.split('|')[0] + '\n';
        tf_textarea.text += '05: ' + this.attribute.split('|')[1] + '\n';
        tf_textarea.text += '06: ' + this.attribute.split('|')[2] + '\n';
        tf_textarea.text += '07: ' + this.attribute.split('|')[3] + '\n';
        tf_textarea.text += '\n';
        tf_textarea.text += '08: ' + this.product.split(',')[0] + '\n';
        tf_textarea.text += '09: ' + this.product.split(',')[1] + '\n';
        tf_textarea.text += '10: ' + this.product.split(',')[2] + '\n';
        tf_textarea.text += '11: ' + this.product.split(',')[3] + '\n';
        tf_textarea.text += '12: ' + this.product.split(',')[4] + '\n';
        tf_textarea.text += '\n';
        tf_textarea.text += '13: ' + this.product.split(',')[0].split('|')[0] + '\n';
        tf_textarea.text += '14: ' + this.product.split(',')[0].split('|')[1] + '\n';
        tf_textarea.text += '15: ' + this.product.split(',')[0].split('|')[2] + '\n';
        tf_textarea.text += '16: ' + this.product.split(',')[0].split('|')[3] + '\n';
        tf_textarea.text += '\n';
        tf_textarea.text += '17: ' + tmp_array[1].split('|')[0] + '\n';
        tf_textarea.text += '18: ' + tmp_array[1].split('|')[1] + '\n';
        tf_textarea.text += '19: ' + product_array[1][2] + '\n';
        tf_textarea.text += '20: ' + product_array[1][3] + '\n';
        tf_textarea.text += '\n';
        textarea += '21: ' + product_array[2][0] + '\n';
        textarea += '22: ' + product_array[2][1] + '\n';
        textarea += '\n';
        //trace(this.title);
    } else {
        //trace('error');
    }
}
product_vars.load("product.txt");

[product_txt.swf]



[product_txt.html]
<embed src="http://www.hompydesign.com/flash/sample/product_txt.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="520" height="420" base="http://www.hompydesign.com/flash/sample/"></embed>

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info

댓글을 달아 주세요

플래시로 외부 파일 데이터를 가져오기 위한 웹서버와 통신하기 샘플 소스 코드입니다. 플래시 액션스크립트 초급자를 위해 학습용으로 부담없이 테스트할 수 있도록 만들었으므로 차근 차근 살펴 보시면 이해에 도움이 될 것이라 생각됩니다. XML 로 규격화된 자료 파일을 플래시에서 읽을 수 있다는 것은 자료에 근거하여 어플리케이션 처럼 동작하는 동적 플래시를 만들 수 있는 장점이 있습니다. 플래시로 XML 객체를 어떻게 다루는지 잘 익혀두시고 차후에 쓸만한 플래시 만드는 일에 잘 활용해보세요.

[product.xml]
<?xml version="1.0" encoding="euc-kr" ?>
<product>
    <item>
        <name>desktop</name>
        <price>380000</price>
        <total>10</total>
        <date>2008-10-01</date>
    </item>
    <item>
        <name>monitor</name>
        <price>270000</price>
        <total>5</total>
        <date>2008-10-04</date>
    </item>
    <item>
        <name>printer</name>
        <price>160000</price>
        <total>2</total>
        <date>2008-09-28</date>
    </item>
    <item>
        <name>notebook</name>
        <price>870000</price>
        <total>15</total>
        <date>2008-10-06</date>
    </item>
    <item>
        <name>mouse</name>
        <price>12000</price>
        <total>20</total>
        <date>2008-09-20</date>
    </item>
</product>


[product_xml.fla]
System.useCodepage = true;
function product_loader() {
    var product_xml = this.firstChild.childNodes;
    var product_len = product_xml.length;
    var item_xml = product_xml[0].childNodes;
    var item_len = item_xml.length;
    var name_xml = item_xml[0].childNodes;
    var name_len = name_xml.length;
    tf_textarea.text += '[xml file tester]\n';
    tf_textarea.text += '01: ' + product_len + "\n";
    tf_textarea.text += '02: ' + product_xml + "\n";
    tf_textarea.text += '03: ' + item_len + "\n";
    tf_textarea.text += '04: ' + item_xml + "\n";
    tf_textarea.text += '05: ' + name_len + "\n";
    tf_textarea.text += '06: ' + name_xml + "\n";
    tf_textarea.text += '\n';
    tf_textarea.text += '07: ' + item_xml[0].nodeName + "\n";
    tf_textarea.text += '08: ' + item_xml[0].firstChild.nodeValue + "\n";
    tf_textarea.text += '07: ' + item_xml[1].nodeName + "\n";
    tf_textarea.text += '08: ' + item_xml[1].firstChild.nodeValue + "\n";
    tf_textarea.text += '09: ' + item_xml[2].nodeName + "\n";
    tf_textarea.text += '10: ' + item_xml[2].firstChild.nodeValue + "\n";
    tf_textarea.text += '11: ' + item_xml[3].nodeName + "\n";
    tf_textarea.text += '12: ' + item_xml[3].firstChild.nodeValue + "\n";
    tf_textarea.text += '\n';
    textarea += '13: ' + product_xml[3].childNodes[0].nodeName + "\n";
    textarea += '14: ' + product_xml[3].childNodes[0].firstChild.nodeValue + "\n";
    textarea += '15: ' + product_xml[3].childNodes[1].nodeName + "\n";
    textarea += '16: ' + product_xml[3].childNodes[1].firstChild.nodeValue + "\n";
    textarea += '17: ' + product_xml[3].childNodes[2].nodeName + "\n";
    textarea += '18: ' + product_xml[3].childNodes[2].firstChild.nodeValue + "\n";
    textarea += '19: ' + product_xml[3].childNodes[3].nodeName + "\n";
    textarea += '20: ' + product_xml[3].childNodes[3].firstChild.nodeValue + "\n";
    tf_textarea.text += '\n';
    textarea += '21: ' + product_xml[3].firstChild.nextSibling.nodeName + "\n";
    textarea += '22: ' + product_xml[3].firstChild.nextSibling.nextSibling.nodeName + "\n";
    /*
    trace('product len = ' + product_len);
    trace('product xml = ' + product_xml);
    trace('item len = ' + item_len);
    trace('item xml = ' + item_xml);
    trace('name len = ' + name_len);
    trace('name xml = ' + name_xml);
    */
}
my_xml = new XML();
my_xml.onLoad = product_loader;
my_xml.ignoreWhite = true;
my_xml.load("product.xml");

[product_xml.swf]
 

[product_xml.html]
<embed
src="http://www.hompydesign.com/flash/sample/product_xml.swf" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="520" height="420" base="http://www.hompydesign.com/flash/sample/"></embed>

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info

댓글을 달아 주세요

  1. ^.^ 2008/10/22 15:54  댓글주소  수정/삭제  댓글쓰기

    node childnode 구분해서 보라고 올려두신거 같네요 ㅋㅋㅋ

사용자 삽입 이미지
그동안 역삼동에 있는 직장 사무실에 있는 회의실을 이용해서 플래시 스터디를 진행했었는데 어제는 처음으로 사무실 밖으로 나와 신촌에 있는 미플(meeple)이라 불리는 곳에 있는 스터디룸을 이용하게 되었습니다. 1인당 대략 5~6천원의 비용으로 노트북과 프로젝터도 빌리고 음료수도 마시며 가볍게 스터디를 할 수 있는 곳이었습니다. 우리 스터디는 노트북이 없으면 스터디를 진행할 수 없는데 어제는 노트북이 모두 대여가 되어서 기다려야 된다고 해서 진행에 차질이 있었습니다. 사전에 노트북을 예약하려고 했으나 현장에서 예약을 해야 된다고 해서 그렇게만 알고 현장에 갔더니 문제가 있었지만 대여 노트북의 성능이 좀 떨어지는 문제도 있고 하니 다음 번 스터디에서는 최소 1대 정도의 성능 좋은 개인 노트북은 준비해야 될 것 같습니다. 노트북 대여 문제를 제외 하곤 다소간 만족 스러운 곳이었고 앞으로는 자주 이용하려고 합니다. 그동안 좁은 19인치 모니터에 의지해서 여러명이 눈을 부릅뜨고 작은 화면을 봐야 하는 불편함을 감수하며 스터디를 진행했었는데 앞으로는 프로젝터를 활용해서 넓은 화면으로 편안하게 스터디를 진행하게 될 것 같습니다. 미처 느끼지 못했던 프로젝터의 넓은 화면을 즐길 수 있는 편안함을 알고 나니 한 대 사서 사무실에서 이용해 볼까 하는 충동을 잠깐 느꼈습니다. 혼자서 또는 소수가 저렴한 비용으로 밝은 분위기에서 차를 마시며 가벼운 학습이나 업무를 진행하기에도 좋을 것 같네요. 집에서 홀로 학습 시간을 보내기 지루할 때 가끔 들러서 이용해봐도 좋겠습니다. 나중에 능력과 기회가 된다면 이런 스타일의 시설을 만들어보고 싶네요.

사용자 삽입 이미지

사용자 삽입 이미지

사용자 삽입 이미지

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info

댓글을 달아 주세요

  1. 씨즌 2008/10/09 00:40  댓글주소  수정/삭제  댓글쓰기

    가고싶다..ㅠㅠ

오늘 오후에 있을 플래시 스터디 과제인 막대 그래프 만들기에 대한 이해를 돕기 위해 간소화 시킨 플래시 차트 소스를 준비했습니다. 그래프 막대로 사용하기 위해 다섯 가지 색상의 무비클립을 만들었습니다. 차트에 적용할 데이터는 2차원 배열에 담았고 Tween 클래스를 활용해 막대 그래프에 활력을 불어 넣었습니다. 여러가지 Tween 클래스 효과를 실험하기 위해 onEnterFrame 이벤트를 이용해 5가지 다른 스타일을 일정한 시간 간격으로 보여주고 있습니다. 플래시 입문자들은 아래 소스를 수정하고 개선해 보시면 플래시 액션스크립트 학습이 도움이 될 것입니다. 뭐든 직접 해보는 것이 중요하므로 손수 멋진 디자인을 입혀서 자신만의 개성있는 막대 그래프를 만들어보세요.

 


import mx.transitions.Tween;
import mx.transitions.easing.*;

var chart_array = Array(
    Array('80','94','70','80','60')
    ,Array('60','100','78','50','80')
    ,Array('90','80','100','75','95')
);

var style_array = Array(
    Strong.easeOut, Elastic.easeOut, Bounce.easeOut, Regular.easeOut, Back.easeOut
);

var menu_max = chart_array.length;
var part_max = chart_array[0].length;
var time_step = 0, style_pos = 0;

function show_chart(set_style){
var i, j, y1, y2, style, mc;
    y1 = 0;
    for (i=0;i<part_max;i++) {
        for (j=0;j<menu_max;j++) {
            mc = this['mc_bar_'+j+'_'+i];
            y2 = chart_array[j][i] * 2;
            style = style_array[set_style];
            new Tween(mc,"_yscale",style,y1,y2,20,false);
        }
    }
}

this.onEnterFrame = function(){
    if (time_step>100) time_step = 0;
    if (time_step==0) {
        show_chart(style_pos);
        style_pos = (style_pos+1)%5;
    }
    time_step ++;
}

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info

댓글을 달아 주세요

이미지 슬라이더는 좁은 공간에 좀더 많은 것을 보기 좋게 보여주기 위해 유용한 유저 인터페이스입니다. 아래 소개하는 내용은 이번 플래시 스터디 과제를 해결하기 위한 힌트이기도 하며 플래시 액션스크립트 초급자를 위한 학습용 플래시 소스이기도 합니다. Tween 클래스를 사용해서 매끄러운 배너 이동에 적용했으며 주기적으로 반복해서 함수를 실행하게 해주는 setInterval 함수를 이용해 일정 시간 간격으로 배너를 교체하도록 하였습니다. 그리고 마우스를 배너 위에 올렸을 경우 clearInterval 함수로 반복하는 것을 중지 하도록 했고 마우스가 배너 위를 벗어났을 때 다시 setInterval 함수를 이용해 다시 반복 하도록 했습니다. 배너의 갯수(menu_max), 배너의 폭(menu_width), 이동 시간 간격(show_time), 어떤 스타일로 이동할 것인지(show_style)를 변경할 수 있는 변수도 적용하였습니다.
백번 설명하는 것 보다 한번 직접 해보는 것이 플래시 액션스크립트 학습의 지름길입니다. 자신의 필요나 구미에 맞게 아래 플래시 소스를 수정 보완 해보시면 학습에 도움이 될 것입니다. 이렇게 만들어진 플래시는 블로그나 홈페이지 배너로 사용하면 보기 좋을 것이며 실제 많이 사용하고 있기도 합니다.







import mx.transitions.Tween;
import mx.transitions.easing.*;

var menu_pos = 0;
var menu_max = 4;
var menu_width = 200;
var show_style = 0;
var show_time = 4000;
var
menu_distance = menu_width * -1;
var time_id = setInterval(_root,"do_next", show_time);
mc_screen.onRollOver = function (){
    clearInterval(time_id);
}
mc_screen.onRollOut = function (){
    time_id = setInterval(_root,"do_next", show_time);
}
mc_screen.onRelease = function (){
    getURL("http://hompy.info/507","_blank");
}
function do_next(){
    var pos1, pos2, x1, x2;
    pos1 = menu_pos;
    menu_pos = menu_pos + 1;
    pos2 = menu_pos;
    x1 = pos1 * menu_distance;
    x2 = pos2 * menu_distance;
    menu_pos = (menu_pos) % menu_max;
    switch (show_style){
        case 1: new Tween(mc_screen,"_x",Elastic.easeOut,x1,x2,20,false); break;
        case 2: new Tween(mc_screen,"_x",Bounce.easeOut,x1,x2,20,false); break;
        case 3: new Tween(mc_screen,"_x",Regular.easeOut,x1,x2,20,false); break;
        case 4: new Tween(mc_screen,"_x",Back.easeOut,x1,x2,20,false); break;
        default: new Tween(mc_screen,"_x",Strong.easeOut,x1,x2,20,false); break;
    }
    trace (menu_pos+":"+x1+"->"+x2);
}

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info

댓글을 달아 주세요

  1. 임채경 2010/06/23 13:46  댓글주소  수정/삭제  댓글쓰기

    감사합니다!

  2. 학생 2009/04/17 21:33  댓글주소  수정/삭제  댓글쓰기

    굳!
    아주 유용합니다.

얼마전에 "나만의 아날로그 플래시 시계를 직접 만들어 보자." 라는 글로 비교적 손쉽게 만들 수 있는 플래시 시계 제작법에 대해 소개했었습니다. 그러다 문득 자바스크립트로 아날로그 시계를 만들면 어떨까 라는 생각이 들어 검색엔진을 이용해 "javascript analog clock" 라는 키워드로 검색을 했더니 자바스크립트로 만든 아날로그 시계 CoolClock 을 소개하는 홈페이지가 있더군요. 웹문서에서 이미지를 그릴 수 있게 하는 캔버스를 이용해 구현되었으며 IE 에서는 캔버스가 지원이 되지 않는 관계로 ExplorerCanvas 를 이용해서 랜더링 했으나 퍼포먼스가 좀 떨어지는 감이 있습니다. 그리고 개성있는 나만의 시계를 만들 수 있게 스킨도 변경할 수 있도록 되어 있습니다. 관심 있는 분들은 구현되는 모습과 소스를 살펴보시면 자바스크립트 학습에 도움이 될 것 같습니다.
CoolClock 홈페이지가 간혹 열리지 않을 경우가 있습니다. 그래서 몇몇 스킨이 적용된 자바스크립트 아날로그 시계를 확인할 수 있는 별도의 페이지를 만들어놨으니 아래 링크로 작동되는 모습을 확인해 볼 수 있습니다.
http://www.hompydesign.com/javascript/clock/javascript_analog_clock.html

<!--[if IE]><script type="text/javascript" src="excanvas.js"></script><![endif]-->
<script type="text/javascript" src="coolclock.js"></script>
<script type="text/javascript" src="moreskins.js"></script>

<canvas id="s01" class="CoolClock:securephp"></canvas>
<canvas id="s02" class="CoolClock:Tes2"></canvas>
<canvas id="s03" class="CoolClock:Lev"></canvas>
<canvas id="s04" class="CoolClock:Sand"></canvas>
<br/>
<canvas id="s05" class="CoolClock:Sun"></canvas>
<canvas id="s06" class="CoolClock:Tor"></canvas>
<canvas id="s07" class="CoolClock:Cold"></canvas>
<canvas id="s08" class="CoolClock:Babosa"></canvas>

자바스크립트로 아날로그 시계 만드는 다른 방법에 대해 생각해보았는데 시계바늘의 움직임에 따른 투명 배경의 이미지를 만들어 해당 시간에 맞는 시계바늘 이미지만 서로 다른 레이어를 겹쳐 보여주는 형태로 구현을 해도 나쁘지 않을 것 같습니다. 다만 시계 바늘 이미지만 준비하면 시간의 변화에 맞는 회전되는 이미지를 자동으로 생성해주는 툴이 있어야 다양한 이미지의 시계를 손쉽게 제작할 수 있을 듯 싶습니다.
자바스크립트로 이미지를 다루는 것에 대해 이것 저것 살펴보다 보니 플래시 만큼 편한 툴이 없구나 라는 생각이 밀려듭니다.^^

 

[excanvas.js]
// Copyright 2006 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


// Known Issues:
//
// * Patterns are not implemented.
// * Radial gradient are not implemented. The VML version of these look very
//     different from the canvas one.
// * Clipping paths are not implemented.
// * Coordsize. The width and height attribute have higher priority than the
//     width and height style values which isn't correct.
// * Painting mode isn't implemented.
// * Canvas width/height should is using content-box by default. IE in
//     Quirks mode will draw the canvas using border-box. Either change your
//     doctype to HTML5
//     (http://www.whatwg.org/specs/web-apps/current-work/#the-doctype)
//     or use Box Sizing Behavior from WebFX
//     (http://webfx.eae.net/dhtml/boxsizing/boxsizing.html)
// * Optimize. There is always room for speed improvements.

// only add this code if we do not already have a canvas implementation
if (!window.CanvasRenderingContext2D) {

(function () {

    // alias some functions to make (compiled) code shorter
    var m = Math;
    var mr = m.round;
    var ms = m.sin;
    var mc = m.cos;

    // this is used for sub pixel precision
    var Z = 10;
    var Z2 = Z / 2;

    var G_vmlCanvasManager_ = {
        init: function (opt_doc) {
            var doc = opt_doc || document;
            if (/MSIE/.test(navigator.userAgent) && !window.opera) {
                var self = this;
                doc.attachEvent("onreadystatechange", function () {
                    self.init_(doc);
                });
            }
        },

        init_: function (doc) {
            if (doc.readyState == "complete") {
                // create xmlns
                if (!doc.namespaces["g_vml_"]) {
                    doc.namespaces.add("g_vml_", "urn:schemas-microsoft-com:vml");
                }

                // setup default css
                var ss = doc.createStyleSheet();
                ss.cssText = "canvas{display:inline-block;overflow:hidden;" +
                        // default size is 300x150 in Gecko and Opera
                        "text-align:left;width:300px;height:150px}" +
                        "g_vml_\\:*{behavior:url(#default#VML)}";

                // find all canvas elements
                var els = doc.getElementsByTagName("canvas");
                for (var i = 0; i < els.length; i++) {
                    if (!els[i].getContext) {
                        this.initElement(els[i]);
                    }
                }
            }
        },

        fixElement_: function (el) {
            // in IE before version 5.5 we would need to add HTML: to the tag name
            // but we do not care about IE before version 6
            var outerHTML = el.outerHTML;

            var newEl = el.ownerDocument.createElement(outerHTML);
            // if the tag is still open IE has created the children as siblings and
            // it has also created a tag with the name "/FOO"
            if (outerHTML.slice(-2) != "/>") {
                var tagName = "/" + el.tagName;
                var ns;
                // remove content
                while ((ns = el.nextSibling) && ns.tagName != tagName) {
                    ns.removeNode();
                }
                // remove the incorrect closing tag
                if (ns) {
                    ns.removeNode();
                }
            }
            el.parentNode.replaceChild(newEl, el);
            return newEl;
        },

        /**
        * Public initializes a canvas element so that it can be used as canvas
        * element from now on. This is called automatically before the page is
        * loaded but if you are creating elements using createElement you need to
        * make sure this is called on the element.
        * @param {HTMLElement} el The canvas element to initialize.
        * @return {HTMLElement} the element that was created.
        */
        initElement: function (el) {
            el = this.fixElement_(el);
            el.getContext = function () {
                if (this.context_) {
                    return this.context_;
                }
                return this.context_ = new CanvasRenderingContext2D_(this);
            };

            // do not use inline function because that will leak memory
            el.attachEvent('onpropertychange', onPropertyChange);
            el.attachEvent('onresize', onResize);

            var attrs = el.attributes;
            if (attrs.width && attrs.width.specified) {
                // TODO: use runtimeStyle and coordsize
                // el.getContext().setWidth_(attrs.width.nodeValue);
                el.style.width = attrs.width.nodeValue + "px";
            } else {
                el.width = el.clientWidth;
            }
            if (attrs.height && attrs.height.specified) {
                // TODO: use runtimeStyle and coordsize
                // el.getContext().setHeight_(attrs.height.nodeValue);
                el.style.height = attrs.height.nodeValue + "px";
            } else {
                el.height = el.clientHeight;
            }
            //el.getContext().setCoordsize_()
            return el;
        }
    };

    function onPropertyChange(e) {
        var el = e.srcElement;

        switch (e.propertyName) {
            case 'width':
                el.style.width = el.attributes.width.nodeValue + "px";
                el.getContext().clearRect();
                break;
            case 'height':
                el.style.height = el.attributes.height.nodeValue + "px";
                el.getContext().clearRect();
                break;
        }
    }

    function onResize(e) {
        var el = e.srcElement;
        if (el.firstChild) {
            el.firstChild.style.width =     el.clientWidth + 'px';
            el.firstChild.style.height = el.clientHeight + 'px';
        }
    }

    G_vmlCanvasManager_.init();

    // precompute "00" to "FF"
    var dec2hex = [];
    for (var i = 0; i < 16; i++) {
        for (var j = 0; j < 16; j++) {
            dec2hex[i * 16 + j] = i.toString(16) + j.toString(16);
        }
    }

    function createMatrixIdentity() {
        return [
            [1, 0, 0],
            [0, 1, 0],
            [0, 0, 1]
        ];
    }

    function matrixMultiply(m1, m2) {
        var result = createMatrixIdentity();

        for (var x = 0; x < 3; x++) {
            for (var y = 0; y < 3; y++) {
                var sum = 0;

                for (var z = 0; z < 3; z++) {
                    sum += m1[x][z] * m2[z][y];
                }

                result[x][y] = sum;
            }
        }
        return result;
    }

    function copyState(o1, o2) {
        o2.fillStyle         = o1.fillStyle;
        o2.lineCap             = o1.lineCap;
        o2.lineJoin             = o1.lineJoin;
        o2.lineWidth         = o1.lineWidth;
        o2.miterLimit         = o1.miterLimit;
        o2.shadowBlur         = o1.shadowBlur;
        o2.shadowColor     = o1.shadowColor;
        o2.shadowOffsetX = o1.shadowOffsetX;
        o2.shadowOffsetY = o1.shadowOffsetY;
        o2.strokeStyle     = o1.strokeStyle;
        o2.arcScaleX_         = o1.arcScaleX_;
        o2.arcScaleY_         = o1.arcScaleY_;
    }

    function processStyle(styleString) {
        var str, alpha = 1;

        styleString = String(styleString);
        if (styleString.substring(0, 3) == "rgb") {
            var start = styleString.indexOf("(", 3);
            var end = styleString.indexOf(")", start + 1);
            var guts = styleString.substring(start + 1, end).split(",");

            str = "#";
            for (var i = 0; i < 3; i++) {
                str += dec2hex[Number(guts[i])];
            }

            if ((guts.length == 4) && (styleString.substr(3, 1) == "a")) {
                alpha = guts[3];
            }
        } else {
            str = styleString;
        }

        return [str, alpha];
    }

    function processLineCap(lineCap) {
        switch (lineCap) {
            case "butt":
                return "flat";
            case "round":
                return "round";
            case "square":
            default:
                return "square";
        }
    }

    /**
    * This class implements CanvasRenderingContext2D interface as described by
    * the WHATWG.
    * @param {HTMLElement} surfaceElement The element that the 2D context should
    * be associated with
    */
    function CanvasRenderingContext2D_(surfaceElement) {
        this.m_ = createMatrixIdentity();

        this.mStack_ = [];
        this.aStack_ = [];
        this.currentPath_ = [];

        // Canvas context properties
        this.strokeStyle = "#000";
        this.fillStyle = "#000";

        this.lineWidth = 1;
        this.lineJoin = "miter";
        this.lineCap = "butt";
        this.miterLimit = Z * 1;
        this.globalAlpha = 1;
        this.canvas = surfaceElement;

        var el = surfaceElement.ownerDocument.createElement('div');
        el.style.width =     surfaceElement.clientWidth + 'px';
        el.style.height = surfaceElement.clientHeight + 'px';
        el.style.overflow = 'hidden';
        el.style.position = 'absolute';
        surfaceElement.appendChild(el);

        this.element_ = el;
        this.arcScaleX_ = 1;
        this.arcScaleY_ = 1;
    };

    var contextPrototype = CanvasRenderingContext2D_.prototype;
    contextPrototype.clearRect = function() {
        this.element_.innerHTML = "";
        this.currentPath_ = [];
    };

    contextPrototype.beginPath = function() {
        // TODO: Branch current matrix so that save/restore has no effect
        //             as per safari docs.

        this.currentPath_ = [];
    };

    contextPrototype.moveTo = function(aX, aY) {
        this.currentPath_.push({type: "moveTo", x: aX, y: aY});
        this.currentX_ = aX;
        this.currentY_ = aY;
    };

    contextPrototype.lineTo = function(aX, aY) {
        this.currentPath_.push({type: "lineTo", x: aX, y: aY});
        this.currentX_ = aX;
        this.currentY_ = aY;
    };

    contextPrototype.bezierCurveTo = function(aCP1x, aCP1y,
                                                                                        aCP2x, aCP2y,
                                                                                        aX, aY) {
        this.currentPath_.push({type: "bezierCurveTo",
                                                    cp1x: aCP1x,
                                                    cp1y: aCP1y,
                                                    cp2x: aCP2x,
                                                    cp2y: aCP2y,
                                                    x: aX,
                                                    y: aY});
        this.currentX_ = aX;
        this.currentY_ = aY;
    };

    contextPrototype.quadraticCurveTo = function(aCPx, aCPy, aX, aY) {
        // the following is lifted almost directly from
        // http://developer.mozilla.org/en/docs/Canvas_tutorial:Drawing_shapes
        var cp1x = this.currentX_ + 2.0 / 3.0 * (aCPx - this.currentX_);
        var cp1y = this.currentY_ + 2.0 / 3.0 * (aCPy - this.currentY_);
        var cp2x = cp1x + (aX - this.currentX_) / 3.0;
        var cp2y = cp1y + (aY - this.currentY_) / 3.0;
        this.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, aX, aY);
    };

    contextPrototype.arc = function(aX, aY, aRadius,
                                                                    aStartAngle, aEndAngle, aClockwise) {
        aRadius *= Z;
        var arcType = aClockwise ? "at" : "wa";

        var xStart = aX + (mc(aStartAngle) * aRadius) - Z2;
        var yStart = aY + (ms(aStartAngle) * aRadius) - Z2;

        var xEnd = aX + (mc(aEndAngle) * aRadius) - Z2;
        var yEnd = aY + (ms(aEndAngle) * aRadius) - Z2;

        // IE won't render arches drawn counter clockwise if xStart == xEnd.
        if (xStart == xEnd && !aClockwise) {
            xStart += 0.125; // Offset xStart by 1/80 of a pixel. Use something
                                            // that can be represented in binary
        }

        this.currentPath_.push({type: arcType,
                                                    x: aX,
                                                    y: aY,
                                                    radius: aRadius,
                                                    xStart: xStart,
                                                    yStart: yStart,
                                                    xEnd: xEnd,
                                                    yEnd: yEnd});

    };

    contextPrototype.rect = function(aX, aY, aWidth, aHeight) {
        this.moveTo(aX, aY);
        this.lineTo(aX + aWidth, aY);
        this.lineTo(aX + aWidth, aY + aHeight);
        this.lineTo(aX, aY + aHeight);
        this.closePath();
    };

    contextPrototype.strokeRect = function(aX, aY, aWidth, aHeight) {
        // Will destroy any existing path (same as FF behaviour)
        this.beginPath();
        this.moveTo(aX, aY);
        this.lineTo(aX + aWidth, aY);
        this.lineTo(aX + aWidth, aY + aHeight);
        this.lineTo(aX, aY + aHeight);
        this.closePath();
        this.stroke();
    };

    contextPrototype.fillRect = function(aX, aY, aWidth, aHeight) {
        // Will destroy any existing path (same as FF behaviour)
        this.beginPath();
        this.moveTo(aX, aY);
        this.lineTo(aX + aWidth, aY);
        this.lineTo(aX + aWidth, aY + aHeight);
        this.lineTo(aX, aY + aHeight);
        this.closePath();
        this.fill();
    };

    contextPrototype.createLinearGradient = function(aX0, aY0, aX1, aY1) {
        var gradient = new CanvasGradient_("gradient");
        return gradient;
    };

    contextPrototype.createRadialGradient = function(aX0, aY0,
                                                                                                    aR0, aX1,
                                                                                                    aY1, aR1) {
        var gradient = new CanvasGradient_("gradientradial");
        gradient.radius1_ = aR0;
        gradient.radius2_ = aR1;
        gradient.focus_.x = aX0;
        gradient.focus_.y = aY0;
        return gradient;
    };

    contextPrototype.drawImage = function (image, var_args) {
        var dx, dy, dw, dh, sx, sy, sw, sh;

        // to find the original width we overide the width and height
        var oldRuntimeWidth = image.runtimeStyle.width;
        var oldRuntimeHeight = image.runtimeStyle.height;
        image.runtimeStyle.width = 'auto';
        image.runtimeStyle.height = 'auto';

        // get the original size
        var w = image.width;
        var h = image.height;

        // and remove overides
        image.runtimeStyle.width = oldRuntimeWidth;
        image.runtimeStyle.height = oldRuntimeHeight;

        if (arguments.length == 3) {
            dx = arguments[1];
            dy = arguments[2];
            sx = sy = 0;
            sw = dw = w;
            sh = dh = h;
        } else if (arguments.length == 5) {
            dx = arguments[1];
            dy = arguments[2];
            dw = arguments[3];
            dh = arguments[4];
            sx = sy = 0;
            sw = w;
            sh = h;
        } else if (arguments.length == 9) {
            sx = arguments[1];
            sy = arguments[2];
            sw = arguments[3];
            sh = arguments[4];
            dx = arguments[5];
            dy = arguments[6];
            dw = arguments[7];
            dh = arguments[8];
        } else {
            throw "Invalid number of arguments";
        }

        var d = this.getCoords_(dx, dy);

        var w2 = sw / 2;
        var h2 = sh / 2;

        var vmlStr = [];

        var W = 10;
        var H = 10;

        // For some reason that I've now forgotten, using divs didn't work
        vmlStr.push(' <g_vml_:group',
                                ' coordsize="', Z * W, ',', Z * H, '"',
                                ' coordorigin="0,0"' ,
                                ' style="width:', W, ';height:', H, ';position:absolute;');

        // If filters are necessary (rotation exists), create them
        // filters are bog-slow, so only create them if abbsolutely necessary
        // The following check doesn't account for skews (which don't exist
        // in the canvas spec (yet) anyway.

        if (this.m_[0][0] != 1 || this.m_[0][1]) {
            var filter = [];

            // Note the 12/21 reversal
            filter.push("M11='", this.m_[0][0], "',",
                                    "M12='", this.m_[1][0], "',",
                                    "M21='", this.m_[0][1], "',",
                                    "M22='", this.m_[1][1], "',",
                                    "Dx='", mr(d.x / Z), "',",
                                    "Dy='", mr(d.y / Z), "'");

            // Bounding box calculation (need to minimize displayed area so that
            // filters don't waste time on unused pixels.
            var max = d;
            var c2 = this.getCoords_(dx + dw, dy);
            var c3 = this.getCoords_(dx, dy + dh);
            var c4 = this.getCoords_(dx + dw, dy + dh);

            max.x = Math.max(max.x, c2.x, c3.x, c4.x);
            max.y = Math.max(max.y, c2.y, c3.y, c4.y);

            vmlStr.push("padding:0 ", mr(max.x / Z), "px ", mr(max.y / Z),
                                    "px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",
                                    filter.join(""), ", sizingmethod='clip');")
        } else {
            vmlStr.push("top:", mr(d.y / Z), "px;left:", mr(d.x / Z), "px;")
        }

        vmlStr.push(' ">' ,
                                '<g_vml_:image src="', image.src, '"',
                                ' style="width:', Z * dw, ';',
                                ' height:', Z * dh, ';"',
                                ' cropleft="', sx / w, '"',
                                ' croptop="', sy / h, '"',
                                ' cropright="', (w - sx - sw) / w, '"',
                                ' cropbottom="', (h - sy - sh) / h, '"',
                                ' />',
                                '</g_vml_:group>');

        this.element_.insertAdjacentHTML("BeforeEnd",
                                                                        vmlStr.join(""));
    };

    contextPrototype.stroke = function(aFill) {
        var lineStr = [];
        var lineOpen = false;
        var a = processStyle(aFill ? this.fillStyle : this.strokeStyle);
        var color = a[0];
        var opacity = a[1] * this.globalAlpha;

        var W = 10;
        var H = 10;

        lineStr.push('<g_vml_:shape',
                                ' fillcolor="', color, '"',
                                ' filled="', Boolean(aFill), '"',
                                ' style="position:absolute;width:', W, ';height:', H, ';"',
                                ' coordorigin="0 0" coordsize="', Z * W, ' ', Z * H, '"',
                                ' stroked="', !aFill, '"',
                                ' strokeweight="', this.lineWidth, '"',
                                ' strokecolor="', color, '"',
                                ' path="');

        var newSeq = false;
        var min = {x: null, y: null};
        var max = {x: null, y: null};

        for (var i = 0; i < this.currentPath_.length; i++) {
            var p = this.currentPath_[i];

            if (p.type == "moveTo") {
                lineStr.push(" m ");
                var c = this.getCoords_(p.x, p.y);
                lineStr.push(mr(c.x), ",", mr(c.y));
            } else if (p.type == "lineTo") {
                lineStr.push(" l ");
                var c = this.getCoords_(p.x, p.y);
                lineStr.push(mr(c.x), ",", mr(c.y));
            } else if (p.type == "close") {
                lineStr.push(" x ");
            } else if (p.type == "bezierCurveTo") {
                lineStr.push(" c ");
                var c = this.getCoords_(p.x, p.y);
                var c1 = this.getCoords_(p.cp1x, p.cp1y);
                var c2 = this.getCoords_(p.cp2x, p.cp2y);
                lineStr.push(mr(c1.x), ",", mr(c1.y), ",",
                                        mr(c2.x), ",", mr(c2.y), ",",
                                        mr(c.x), ",", mr(c.y));
            } else if (p.type == "at" || p.type == "wa") {
                lineStr.push(" ", p.type, " ");
                var c     = this.getCoords_(p.x, p.y);
                var cStart = this.getCoords_(p.xStart, p.yStart);
                var cEnd = this.getCoords_(p.xEnd, p.yEnd);

                lineStr.push(mr(c.x - this.arcScaleX_ * p.radius), ",",
                                        mr(c.y - this.arcScaleY_ * p.radius), " ",
                                        mr(c.x + this.arcScaleX_ * p.radius), ",",
                                        mr(c.y + this.arcScaleY_ * p.radius), " ",
                                        mr(cStart.x), ",", mr(cStart.y), " ",
                                        mr(cEnd.x), ",", mr(cEnd.y));
            }


            // TODO: Following is broken for curves due to
            //             move to proper paths.

            // Figure out dimensions so we can do gradient fills
            // properly
            if(c) {
                if (min.x == null || c.x < min.x) {
                    min.x = c.x;
                }
                if (max.x == null || c.x > max.x) {
                    max.x = c.x;
                }
                if (min.y == null || c.y < min.y) {
                    min.y = c.y;
                }
                if (max.y == null || c.y > max.y) {
                    max.y = c.y;
                }
            }
        }
        lineStr.push(' ">');

        if (typeof this.fillStyle == "object") {
            var focus = {x: "50%", y: "50%"};
            var width = (max.x - min.x);
            var height = (max.y - min.y);
            var dimension = (width > height) ? width : height;

            focus.x = mr((this.fillStyle.focus_.x / width) * 100 + 50) + "%";
            focus.y = mr((this.fillStyle.focus_.y / height) * 100 + 50) + "%";

            var colors = [];

            // inside radius (%)
            if (this.fillStyle.type_ == "gradientradial") {
                var inside = (this.fillStyle.radius1_ / dimension * 100);

                // percentage that outside radius exceeds inside radius
                var expansion = (this.fillStyle.radius2_ / dimension * 100) - inside;
            } else {
                var inside = 0;
                var expansion = 100;
            }

            var insidecolor = {offset: null, color: null};
            var outsidecolor = {offset: null, color: null};

            // We need to sort 'colors' by percentage, from 0 > 100 otherwise ie
            // won't interpret it correctly
            this.fillStyle.colors_.sort(function (cs1, cs2) {
                return cs1.offset - cs2.offset;
            });

            for (var i = 0; i < this.fillStyle.colors_.length; i++) {
                var fs = this.fillStyle.colors_[i];

                colors.push( (fs.offset * expansion) + inside, "% ", fs.color, ",");

                if (fs.offset > insidecolor.offset || insidecolor.offset == null) {
                    insidecolor.offset = fs.offset;
                    insidecolor.color = fs.color;
                }

                if (fs.offset < outsidecolor.offset || outsidecolor.offset == null) {
                    outsidecolor.offset = fs.offset;
                    outsidecolor.color = fs.color;
                }
            }
            colors.pop();

            lineStr.push('<g_vml_:fill',
                                    ' color="', outsidecolor.color, '"',
                                    ' color2="', insidecolor.color, '"',
                                    ' type="', this.fillStyle.type_, '"',
                                    ' focusposition="', focus.x, ', ', focus.y, '"',
                                    ' colors="', colors.join(""), '"',
                                    ' opacity="', opacity, '" />');
        } else if (aFill) {
            lineStr.push('<g_vml_:fill color="', color, '" opacity="', opacity, '" />');
        } else {
            lineStr.push(
                '<g_vml_:stroke',
                ' opacity="', opacity,'"',
                ' joinstyle="', this.lineJoin, '"',
                ' miterlimit="', this.miterLimit, '"',
                ' endcap="', processLineCap(this.lineCap) ,'"',
                ' weight="', this.lineWidth, 'px"',
                ' color="', color,'" />'
            );
        }

        lineStr.push("</g_vml_:shape>");

        this.element_.insertAdjacentHTML("beforeEnd", lineStr.join(""));

        this.currentPath_ = [];
    };

    contextPrototype.fill = function() {
        this.stroke(true);
    }

    contextPrototype.closePath = function() {
        this.currentPath_.push({type: "close"});
    };

    /**
    * @private
    */
    contextPrototype.getCoords_ = function(aX, aY) {
        return {
            x: Z * (aX * this.m_[0][0] + aY * this.m_[1][0] + this.m_[2][0]) - Z2,
            y: Z * (aX * this.m_[0][1] + aY * this.m_[1][1] + this.m_[2][1]) - Z2
        }
    };

    contextPrototype.save = function() {
        var o = {};
        copyState(this, o);
        this.aStack_.push(o);
        this.mStack_.push(this.m_);
        this.m_ = matrixMultiply(createMatrixIdentity(), this.m_);
    };

    contextPrototype.restore = function() {
        copyState(this.aStack_.pop(), this);
        this.m_ = this.mStack_.pop();
    };

    contextPrototype.translate = function(aX, aY) {
        var m1 = [
            [1,     0,     0],
            [0,     1,     0],
            [aX, aY, 1]
        ];

        this.m_ = matrixMultiply(m1, this.m_);
    };

    contextPrototype.rotate = function(aRot) {
        var c = mc(aRot);
        var s = ms(aRot);

        var m1 = [
            [c,     s, 0],
            [-s, c, 0],
            [0,     0, 1]
        ];

        this.m_ = matrixMultiply(m1, this.m_);
    };

    contextPrototype.scale = function(aX, aY) {
        this.arcScaleX_ *= aX;
        this.arcScaleY_ *= aY;
        var m1 = [
            [aX, 0,     0],
            [0,     aY, 0],
            [0,     0,     1]
        ];

        this.m_ = matrixMultiply(m1, this.m_);
    };

    /******** STUBS ********/
    contextPrototype.clip = function() {
        // TODO: Implement
    };

    contextPrototype.arcTo = function() {
        // TODO: Implement
    };

    contextPrototype.createPattern = function() {
        return new CanvasPattern_;
    };

    // Gradient / Pattern Stubs
    function CanvasGradient_(aType) {
        this.type_ = aType;
        this.radius1_ = 0;
        this.radius2_ = 0;
        this.colors_ = [];
        this.focus_ = {x: 0, y: 0};
    }

    CanvasGradient_.prototype.addColorStop = function(aOffset, aColor) {
        aColor = processStyle(aColor);
        this.colors_.push({offset: 1-aOffset, color: aColor});
    };

    function CanvasPattern_() {}

    // set up externs
    G_vmlCanvasManager = G_vmlCanvasManager_;
    CanvasRenderingContext2D = CanvasRenderingContext2D_;
    CanvasGradient = CanvasGradient_;
    CanvasPattern = CanvasPattern_;

})();

} // if

[coolclock.js]
/*
CoolClock by Simon Baird (simon dot baird at gmail dot com)
Version 1.0.6 (08-Jul-2008)
See http://simonbaird.com/coolclock/

Copyright (c) Simon Baird 2006-2008

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

Neither the name of the Simon Baird nor the names of other contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
*/

window.CoolClock = function(canvasId,displayRadius,skinId,showSecondHand,gmtOffset) {
    return this.init(canvasId,displayRadius,skinId,showSecondHand,gmtOffset);
}

CoolClock.findAndCreateClocks = function() {
    var canvases = document.getElementsByTagName("canvas");
    for (var i=0;i<canvases.length;i++) {
        var fields = canvases[i].className.split(" ")[0].split(":");
        if (fields[0] == "CoolClock") {
            new CoolClock(canvases[i].id,fields[2],fields[1],fields[3]!="noSeconds",fields[4]);
        }
    }
}

// borrowed from behaviour.js
// actually doesn't work right unless it's at the end of html document
// hence can't have a body onload
// this is a bug. FIXME
// maybe have a setTimeout hack??
CoolClock.addLoadEvent = function(func){
    var oldonload = window.onload;
    if (typeof window.onload != 'function')
        window.onload = func;
    else
        window.onload = function() {
            oldonload();
            func();
        }
}

CoolClock.config = {
    clockTracker: {},
    tickDelay: 1000,
    longTickDelay: 15000,
    defaultRadius: 85,
    renderRadius: 100,
    defaultSkin: "swissRail",
    skins:     {
        // more skins in moreskins.js
        // try making your own...

        swissRail: {
            outerBorder: { lineWidth: 1, radius:95, color: "black", alpha: 1 },
            smallIndicator: { lineWidth: 2, startAt: 89, endAt: 93, color: "black", alpha: 1 },
            largeIndicator: { lineWidth: 4, startAt: 80, endAt: 93, color: "black", alpha: 1 },
            hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "black", alpha: 1 },
            minuteHand: { lineWidth: 7, startAt: -15, endAt: 75, color: "black", alpha: 1 },
            secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: 1 },
            secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "red", color: "red", alpha: 1 }
        },
        chunkySwiss: {
            outerBorder: { lineWidth: 4, radius:97, color: "black", alpha: 1 },
            smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "black", alpha: 1 },
            largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "black", alpha: 1 },
            hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "black", alpha: 1 },
            minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "black", alpha: 1 },
            secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 },
            secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 }
        },
        chunkySwissOnBlack: {
            outerBorder: { lineWidth: 4, radius:97, color: "white", alpha: 1 },
            smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "white", alpha: 1 },
            largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "white", alpha: 1 },
            hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "white", alpha: 1 },
            minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "white", alpha: 1 },
            secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 },
            secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 }
        }

    }
};

CoolClock.prototype = {
    init: function(canvasId,displayRadius,skinId,showSecondHand,gmtOffset) {
        this.canvasId = canvasId;
        this.displayRadius = displayRadius || CoolClock.config.defaultRadius;
        this.skinId = skinId || CoolClock.config.defaultSkin;
        this.showSecondHand = typeof showSecondHand == "boolean" ? showSecondHand : true;
        this.tickDelay = CoolClock.config[ this.showSecondHand ? "tickDelay" : "longTickDelay"];

        this.canvas = document.getElementById(canvasId);

        this.canvas.setAttribute("width",this.displayRadius*2);
        this.canvas.setAttribute("height",this.displayRadius*2);

        this.canvas.style.width = this.displayRadius*2 + "px";
        this.canvas.style.height = this.displayRadius*2 + "px";

        this.renderRadius = CoolClock.config.renderRadius;

        this.scale = this.displayRadius / this.renderRadius;
        this.ctx = this.canvas.getContext("2d");
        this.ctx.scale(this.scale,this.scale);

        this.gmtOffset = gmtOffset != null ? parseFloat(gmtOffset) : gmtOffset;

        CoolClock.config.clockTracker[canvasId] = this;
        this.tick();
        return this;
    },

    fullCircle: function(skin) {
        this.fullCircleAt(this.renderRadius,this.renderRadius,skin);
    },

    fullCircleAt: function(x,y,skin) {
        with (this.ctx) {
            save();
            globalAlpha = skin.alpha;
            lineWidth = skin.lineWidth;
            if (!document.all)
                beginPath();
            if (document.all)
                // excanvas doesn't scale line width so we will do it here
                lineWidth = lineWidth * this.scale;
            arc(x, y, skin.radius, 0, 2*Math.PI, false);
            if (document.all)
                // excanvas doesn't close the circle so let's color in the gap
                arc(x, y, skin.radius, -0.1, 0.1, false);
            if (skin.fillColor) {
                fillStyle = skin.fillColor
                fill();
            }
            else {
                // XXX why not stroke and fill
                strokeStyle = skin.color;
                stroke();
            }
            restore();
        }
    },

    radialLineAtAngle: function(angleFraction,skin) {
        with (this.ctx) {
            save();
            translate(this.renderRadius,this.renderRadius);
            rotate(Math.PI * (2 * angleFraction - 0.5));
            globalAlpha = skin.alpha;
            strokeStyle = skin.color;
            lineWidth = skin.lineWidth;
            if (document.all)
                // excanvas doesn't scale line width so we will do it here
                lineWidth = lineWidth * this.scale;
            if (skin.radius) {
                this.fullCircleAt(skin.startAt,0,skin)
            }
            else {
                beginPath();
                moveTo(skin.startAt,0)
                lineTo(skin.endAt,0);
                stroke();
            }
            restore();
        }
    },

    render: function(hour,min,sec) {
        var skin = CoolClock.config.skins[this.skinId];
        this.ctx.clearRect(0,0,this.renderRadius*2,this.renderRadius*2);

        this.fullCircle(skin.outerBorder);

        for (var i=0;i<60;i++)
            this.radialLineAtAngle(i/60,skin[ i%5 ? "smallIndicator" : "largeIndicator"]);
               
        this.radialLineAtAngle((hour+min/60)/12,skin.hourHand);
        this.radialLineAtAngle((min+sec/60)/60,skin.minuteHand);
        if (this.showSecondHand) {
            this.radialLineAtAngle(sec/60,skin.secondHand);
            if (!document.all)
                // decoration doesn't render right in IE so lets turn it off
                this.radialLineAtAngle(sec/60,skin.secondDecoration);
        }
    },


    nextTick: function() {
        setTimeout("CoolClock.config.clockTracker['"+this.canvasId+"'].tick()",this.tickDelay);
    },

    stillHere: function() {
        return document.getElementById(this.canvasId) != null;
    },

    refreshDisplay: function() {
        var now = new Date();
        if (this.gmtOffset != null) {
            // use GMT + gmtOffset
            var offsetNow = new Date(now.valueOf() + (this.gmtOffset * 1000 * 60 * 60));
            this.render(offsetNow.getUTCHours(),offsetNow.getUTCMinutes(),offsetNow.getUTCSeconds());
        }
        else {
            // use local time
            this.render(now.getHours(),now.getMinutes(),now.getSeconds());
        }
    },

    tick: function() {
        if (this.stillHere()) {
            this.refreshDisplay()
            this.nextTick();
        }
    }
}

CoolClock.addLoadEvent(CoolClock.findAndCreateClocks);

[moreskins.js]
CoolClock.config.skins = {

    swissRail: {
        outerBorder: { lineWidth: 1, radius:95, color: "black", alpha: 1 },
        smallIndicator: { lineWidth: 2, startAt: 89, endAt: 93, color: "black", alpha: 1 },
        largeIndicator: { lineWidth: 4, startAt: 80, endAt: 93, color: "black", alpha: 1 },
        hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "black", alpha: 1 },
        minuteHand: { lineWidth: 7, startAt: -15, endAt: 75, color: "black", alpha: 1 },
        secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: 1 },
        secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "red", color: "red", alpha: 1 }
    },

    chunkySwiss: {
        outerBorder: { lineWidth: 4, radius:97, color: "black", alpha: 1 },
        smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "black", alpha: 1 },
        largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "black", alpha: 1 },
        hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "black", alpha: 1 },
        minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "black", alpha: 1 },
        secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 },
        secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 }
    },

    chunkySwissOnBlack: {
        outerBorder: { lineWidth: 4, radius:97, color: "white", alpha: 1 },
        smallIndicator: { lineWidth: 4, startAt: 89, endAt: 93, color: "white", alpha: 1 },
        largeIndicator: { lineWidth: 8, startAt: 80, endAt: 93, color: "white", alpha: 1 },
        hourHand: { lineWidth: 12, startAt: -15, endAt: 60, color: "white", alpha: 1 },
        minuteHand: { lineWidth: 10, startAt: -15, endAt: 85, color: "white", alpha: 1 },
        secondHand: { lineWidth: 4, startAt: -20, endAt: 85, color: "red", alpha: 1 },
        secondDecoration: { lineWidth: 2, startAt: 70, radius: 8, fillColor: "red", color: "red", alpha: 1 }
    },

    fancy: {
        outerBorder: { lineWidth: 5, radius:95, color: "green", alpha: 0.7 },
        smallIndicator: { lineWidth: 1, startAt: 80, endAt: 93, color: "black", alpha: 0.4 },
        largeIndicator: { lineWidth: 1, startAt: 30, endAt: 93, color: "black", alpha: 0.5 },
        hourHand: { lineWidth: 8, startAt: -15, endAt: 50, color: "blue", alpha: 0.7 },
        minuteHand: { lineWidth: 7, startAt: -15, endAt: 92, color: "red", alpha: 0.7 },
        secondHand: { lineWidth: 10, startAt: 80, endAt: 85, color: "blue", alpha: 0.3 },
        secondDecoration: { lineWidth: 1, startAt: 30, radius: 50, fillColor: "blue", color: "red", alpha: 0.15 }
    },

    machine: {
        outerBorder: { lineWidth: 60, radius:55, color: "#dd6655", alpha: 1 },
        smallIndicator: { lineWidth: 4, startAt: 80, endAt: 95, color: "white", alpha: 1 },
        largeIndicator: { lineWidth: 14, startAt: 77, endAt: 92, color: "#dd6655", alpha: 1 },
        hourHand: { lineWidth: 18, startAt: -15, endAt: 40, color: "white", alpha: 1 },
        minuteHand: { lineWidth: 14, startAt: 24, endAt: 100, color: "#771100", alpha: 0.5 },
        secondHand: { lineWidth: 3, startAt: 22, endAt: 83, color: "green", alpha: 0 },
        secondDecoration: { lineWidth: 1, startAt: 52, radius: 26, fillColor: "#ffcccc", color: "red", alpha: 0.5 }
    },

    // these three created by bonstio from http://bonstio.net
    classic/*was gIG*/: {
        outerBorder: { lineWidth: 185, radius:1, color: "#E5ECF9", alpha: 1 },
        smallIndicator: { lineWidth: 2, startAt: 89, endAt: 94, color: "#3366CC", alpha: 1 },
        largeIndicator: { lineWidth: 4, startAt: 83, endAt: 94, color: "#3366CC", alpha: 1 },
        hourHand: { lineWidth: 5, startAt: 0, endAt: 60, color: "black", alpha: 1 },
        minuteHand: { lineWidth: 4, startAt: 0, endAt: 80, color: "black", alpha: 1 },
        secondHand: { lineWidth: 1, startAt: -20, endAt: 85, color: "red", alpha: .85 },
        secondDecoration: { lineWidth: 3, startAt: 0, radius: 2, fillColor: "black", color: "black", alpha: 1 }
    },

    modern/*was gIG2*/: {
        outerBorder: { lineWidth: 185, radius:1, color: "#E5ECF9", alpha: 1 },
        smallIndicator: { lineWidth: 5, startAt: 88, endAt: 94, color: "#3366CC", alpha: 1 },
        largeIndicator: { lineWidth: 5, startAt: 88, endAt: 94, color: "#3366CC", alpha: 1 },
        hourHand: { lineWidth: 8, startAt: 0, endAt: 60, color: "black", alpha: 1 },
        minuteHand: { lineWidth: 8, startAt: 0, endAt: 80, color: "black", alpha: 1 },
        secondHand: { lineWidth: 5, startAt: 80, endAt: 85, color: "red", alpha: .85 },
        secondDecoration: { lineWidth: 3, startAt: 0, radius: 4, fillColor: "black", color: "black", alpha: 1 }
    },

    simple/*was gIG3*/: {
        outerBorder: { lineWidth: 185, radius:1, color: "#E5ECF9", alpha: 1 },
        smallIndicator: { lineWidth: 10, startAt: 90, endAt: 94, color: "#3366CC", alpha: 1 },
        largeIndicator: { lineWidth: 10, startAt: 90, endAt: 94, color: "#3366CC", alpha: 1 },
        hourHand: { lineWidth: 8, startAt: 0, endAt: 60, color: "black", alpha: 1 },
        minuteHand: { lineWidth: 8, startAt: 0, endAt: 80, color: "black", alpha: 1 },
        secondHand: { lineWidth: 5, startAt: 80, endAt: 85, color: "red", alpha: .85 },
        secondDecoration: { lineWidth: 3, startAt: 0, radius: 4, fillColor: "black", color: "black", alpha: 1 }
    },

    // these two by securephp
    securephp: {
        outerBorder: { lineWidth: 100, radius:0.45, color: "#669900", alpha: 0.3 },
        smallIndicator: { lineWidth: 2, startAt: 80, endAt:90 , color: "green", alpha: 1 },
        largeIndicator: { lineWidth: 8.5, startAt: 20, endAt:40 , color: "green", alpha: 0.4 },
        hourHand: { lineWidth: 3, startAt: 0, endAt: 60, color: "black", alpha: 1 },
        minuteHand: { lineWidth: 2, startAt: 0, endAt: 75, color: "black", alpha: 1 },
        secondHand: { lineWidth: 1, startAt: -10, endAt: 80, color: "blue", alpha: 0.8 },
        secondDecoration: { lineWidth: 1, startAt: 70, radius: 4, fillColor: "blue", color: "red", alpha: 1 }
    },

    Tes2: {
        outerBorder: { lineWidth: 4, radius:95, color: "black", alpha: 0.5 },
        smallIndicator: { lineWidth: 1, startAt: 10, endAt:50 , color: "#66CCFF", alpha: 1 },
        largeIndicator: { lineWidth: 8.5, startAt: 60, endAt: 70, color: "#6699FF", alpha: 1 },
        hourHand: { lineWidth: 5, startAt: -15, endAt: 60, color: "black", alpha: 0.7 },
        minuteHand: { lineWidth: 3, startAt: -25, endAt: 75, color: "black", alpha: 0.7 },
        secondHand: { lineWidth: 1.5, startAt: -20, endAt: 88, color: "red", alpha: 1 },
        secondDecoration: { lineWidth: 1, startAt: 20, radius: 4, fillColor: "blue", color: "red", alpha: 1 }
    },


    Lev: {
    outerBorder: { lineWidth:10, radius:95, color: "#CCFF33", alpha: 0.65 },
    smallIndicator: { lineWidth: 5, startAt: 84, endAt: 90, color: "#996600", alpha: 1 },
    largeIndicator: { lineWidth: 40, startAt: 25, endAt: 95, color: "#336600", alpha: 0.55 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 0.9 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 0.85 },
    secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 1 },
    secondDecoration: { lineWidth: 2, startAt: 5, radius: 10, fillColor: "black", color: "black", alpha: 1 }
    },

    Sand: {
    outerBorder: { lineWidth:1, radius:70, color: "black", alpha: 0.5 },
    smallIndicator: { lineWidth: 3, startAt: 50, endAt: 70, color: "#0066FF", alpha: 0.5 },
    largeIndicator: { lineWidth: 200, startAt: 80, endAt: 95, color: "#996600", alpha: 0.75 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 0.9 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 0.85 },
    secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 1 },
    secondDecoration: { lineWidth: 2, startAt: 5, radius: 10, fillColor: "black", color: "black", alpha: 1 }
    },

    Sun: {
    outerBorder: { lineWidth:100, radius:140, color: "#99FFFF", alpha: 0.2 },
    smallIndicator: { lineWidth: 300, startAt: 50, endAt: 70, color: "black", alpha: 0.1 },
    largeIndicator: { lineWidth: 5, startAt: 80, endAt: 95, color: "black", alpha: 0.65 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 0.9 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 0.85 },
    secondHand: { lineWidth: 1, startAt: 0, endAt: 90, color: "black", alpha: 1 },
    secondDecoration: { lineWidth: 2, startAt: 5, radius: 10, fillColor: "black", color: "black", alpha: 1 }
    },

    Tor: {
    outerBorder: { lineWidth:10, radius:88, color: "#996600", alpha: 0.9 },
    smallIndicator: { lineWidth: 6, startAt: -10, endAt: 73, color: "green", alpha: 0.3 },
    largeIndicator: { lineWidth: 6, startAt: 73, endAt: 100, color: "black", alpha: 0.65 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 1 },
    secondHand: { lineWidth: 1, startAt: -73, endAt: 73, color: "black", alpha: 0.8 },
    secondDecoration: { lineWidth: 2, startAt: 5, radius: 10, fillColor: "black", color: "black", alpha: 1 }
    },

    Cold: {
    outerBorder: { lineWidth:15, radius:90, color: "black", alpha: 0.3 },
    smallIndicator: { lineWidth: 15, startAt: -10, endAt: 95, color: "blue", alpha: 0.1 },
    largeIndicator: { lineWidth: 3, startAt: 80, endAt: 95, color: "blue", alpha: 0.65 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 1 },
    secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 0.8 },
    secondDecoration: { lineWidth: 5, startAt: 30, radius: 10, fillColor: "black", color: "black", alpha: 1 }
    },

    Babosa: {
    outerBorder: { lineWidth: 100, radius:25, color: "blue", alpha: 0.25 },
    smallIndicator: { lineWidth: 3, startAt: 90, endAt: 95, color: "#3366CC", alpha: 1 },
    largeIndicator: { lineWidth: 4, startAt: 75, endAt: 95, color: "#3366CC", alpha: 1 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 60, color: "black", alpha: 1 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 85, color: "black", alpha: 1 },
    secondHand: { lineWidth: 12, startAt: 75, endAt: 90, color: "red", alpha: 0.8 },
    secondDecoration: { lineWidth: 3, startAt: 0, radius: 4, fillColor: "black", color: "black", alpha: 1 }
    },

    Tumb: {
    outerBorder: { lineWidth:105, radius:5, color: "green", alpha: 0.4 },
    smallIndicator: { lineWidth: 1, startAt: 93, endAt: 98, color: "green", alpha: 1 },
    largeIndicator: { lineWidth: 50, startAt: 0, endAt: 89, color: "red", alpha: 0.14 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 80, color: "black", alpha: 1 },
    secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 0.8 },
    secondDecoration: { lineWidth: 5, startAt: 50, radius: 90, fillColor: "black", color: "black", alpha: 0.05 }
    },

    Stone: {
    outerBorder: { lineWidth:15, radius:80, color: "#339933", alpha: 0.5 },
    smallIndicator: { lineWidth: 2, startAt: 70, endAt: 90, color: "#FF3300", alpha: 0.7 },
    largeIndicator: { lineWidth: 15, startAt: 0, endAt: 29, color: "#FF6600", alpha: 0.3 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 75, color: "black", alpha: 1 },
    secondHand: { lineWidth: 1, startAt: 0, endAt: 85, color: "black", alpha: 0.8 },
    secondDecoration: { lineWidth: 5, startAt: 50, radius: 90, fillColor: "black", color: "black", alpha: 0.05 }
    },

    Disc: {
    outerBorder: { lineWidth:105, radius:1, color: "#666600", alpha: 0.2 },
    smallIndicator: { lineWidth: 1, startAt: 58, endAt: 95, color: "#669900", alpha: 0.8 },
    largeIndicator: { lineWidth: 6, startAt: 25, endAt: 35, color: "#666600", alpha: 1 },
    hourHand: { lineWidth: 4, startAt: 0, endAt: 65, color: "black", alpha: 1 },
    minuteHand: { lineWidth: 3, startAt: 0, endAt: 75, color: "black", alpha: 1 },
    secondHand: { lineWidth: 1, startAt: -75, endAt: 75, color: "#99CC00", alpha: 0.8 },
    secondDecoration: { lineWidth: 5, startAt: 50, radius: 90, fillColor: "#00FF00", color: "green", alpha: 0.05 }
    }

};


웹프로그래머의 홈페이지 정보 블로그 http://hompy.info

댓글을 달아 주세요

  1. 모꼬모지 2009/10/12 11:15  댓글주소  수정/삭제  댓글쓰기

    아무리 해도 님이 수정하신건.. 안되는 군요..-_-)a
    물론 원출처 것은 잘됩니다.
    환경 xp 익스 6.x

텍스트큐브에서 트랙백 주소 복사 기능에 사용하고 있는 클립보드 복사 기능 구현을 위한 소스 코드입니다. 관련된 소스 코드만 추려낸 것으로 플래시 액션 스크립트 clipboardPoter.as 와 자바스크립트 copy2clipboard.js 그리고 실제 홈페이지에 적용가능한 예제 웹문서 copy2clipboard.html 으로 구성하였습니다.
웹문서에서 자바스크립트 메소드를 이용해서 클립보드 복사가 가능하지만 보안창이 뜨기 때문에 사용자 입장에서 불편함이 있으므로 이를 우회하기 위해 요즘 보편적으로 깔려있는 플래시 환경을 이용하고 있습니다. 플래시 액션스크립트에서 System.setClipboard 메소드를 이용해서 클립보드 복사 기능을 구현하고 있고 플래시 환경이 아닐경우 기존 자바스크립트 복사 메소드 window.clipboardData.setData 를 이용하고 있습니다. 그리고 플래시와 자바스크립트 사이의 통신을 위해 addCallback 메소드를 사용하고 있습니다.
구현 원리에 대해 이해가 되셨으면 아래 소스 코드를 찬찬히 살펴보시고 실무에 적용해보실 수 있습니다.

웹프로그래머의 홈페이지 정보 블로그 http://hompy.info

[clipboardPoter.as]

function setClipBoard(str) {
        System.setClipboard(str);
        flash.external.ExternalInterface.call(callback, true);
}
System.security.allowDomain("*");
var methodName = "setClipBoard";
var instance = null;
var method = setClipBoard;
var wasSuccessful = flash.external.ExternalInterface.addCallback(methodName, instance, method);


[copy2clipboard.js]

function document_write(s){
    document.write(document.getElementById(s).value);
}
var sUserAgent = navigator.userAgent;
var isOpera = sUserAgent.indexOf("Opera") > -1;
var isIE = sUserAgent.indexOf("compatible") > -1
        && sUserAgent.indexOf("MSIE") > -1
        && !isOpera;
function thisMovie(movieName) {
    if (navigator.appName.indexOf("Microsoft") != -1) {
    return document.getElementById(movieName);
    }
    else {
    return document[movieName];
    }
}
function copyUrl(url) {
    try {
        thisMovie('clipboardPoter').setClipBoard(url);
    } catch(e) {
        if(isIE) {
            window.clipboardData.setData('Text',url);
            window.alert("주소가 복사되었습니다.");
        }
    }
}
function onClipBorad(result) {
    alert(result ? "주소가 복사되었습니다." : "주소 복사를 실패했습니다.");
}


[copy2clipboard.html]

<script type='text/javascript'>
window.clipboardPoter = document.getElementById("clipboardPoter");
</script>

<span onclick="copyUrl('http://hompy.info/504')" style="cursor:pointer">http://hompy.info/504</span>

<div style="position:absolute;top:0;left:0; background-color:transparent;background-image:none">
<textarea id="flash_copy_to_clipboard" style="display:none;" rows="0" cols="0">
<OBJECT id="clipboardPoter" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" codebase="http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0" width